1、前言
在OpenLayers
中,轨迹回放的实现方式有两种:一种是监听postcompose
事件,另一种是利用interval
定时器实现,下面开始介绍。
2、轨迹点数据
首先模拟一份轨迹点数据:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Newtonsoft.Json;
namespace RouteApp.ashx
{
/// <summary>
/// GetPointHandler 的摘要说明
/// </summary>
public class GetPointHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
List<Point> points = new List<Point>();
for (int i = 1; i <= 100; i++)
{
points.Add(new Point
{
Longitude = 120.0 + i / 1000.0,
Latitude = 30.0 + i / 1000.0
});
}
for (int i = 1; i <= 100; i++)
{
points.Add(new Point
{
Longitude = 120.1 + i / 1000.0,
Latitude = 30.1
});
}
for (int i = 1; i <= 100; i++)
{
points.Add(new Point
{
Longitude = 120.2 + i / 1000.0,
Latitude = 30.1 + i / 1000.0
});
}
context.Response.Write(JsonConvert.SerializeObject(points));
}
public bool IsReusable
{
get
{
return false;
}
}
}
public class Point
{
/// <summary>
/// 经度
/// </summary>
public double Longitude { get; set; }
/// <summary>
/// 纬度
/// </summary>
public double Latitude { get; set; }
}
}
3、实现方式一
第一种实现方式是通过监听postcompose
事件实现,官网也有例子,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>轨迹回放</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
<script src="lib/jquery/jquery-3.5.1.min.js"></script>
</head>
<body>
<div id="map" style="width:1200px;height:800px;"></div>
<button id="btn">轨迹回放</button>
<script>
// 获取轨迹点
var points = [];
$.ajax({
type: 'get',
url: 'ashx/GetPointHandler.ashx',
dataType: 'json',
async: false,
cache: false,
success: function (res) {
res.forEach(function (point) {
points.push([point.Longitude, point.Latitude]);
})
}
});
// 轨迹
var route = new ol.geom.LineString(points);
var routeCoords = route.getCoordinates();
var routeLength = routeCoords.length;
// 轨迹线要素
var routeFeature = new ol.Feature({
type: 'route',
geometry: route
});
// 轨迹点要素
var geoMarker = new ol.Feature({
type: 'geoMarker',
geometry: new ol.geom.Point(routeCoords[0])
});
// 创建样式
var styles = {
'route': new ol.style.Style({
stroke: new ol.style.Stroke({
width: 5,
color: 'blue'
})
}),
'geoMarker': new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
snapToPixel: false,
fill: new ol.style.Fill({
color: 'red'
}),
})
})
};
var center = [120, 30];
var animating = false;
var speed, now;
// 创建瓦片图层
var tileLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'tile/{z}/{x}/{y}.png'
})
});
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
routeFeature,
geoMarker
]
}),
style: function (feature) {
if (animating && feature.get('type') === 'geoMarker') {
return null;
}
return styles[feature.get('type')];
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
tileLayer,
vectorLayer
],
view: new ol.View({
projection: 'EPSG:4326',
center: center,
zoom: 11
})
});
// 监听事件
var moveFeature = function (event) {
var vectorContext = event.vectorContext;
var frameState = event.frameState;
if (animating) {
var elapsedTime = frameState.time - now;
var index = Math.round(speed * elapsedTime / 1000);
if (index >= routeLength) {
stopAnimation(true);
return;
}
var currentPoint = new ol.geom.Point(routeCoords[index]);
var feature = new ol.Feature(currentPoint);
vectorContext.drawFeature(feature, styles.geoMarker);
}
map.render();
};
// 开始动画
function startAnimation() {
if (animating) {
stopAnimation(false);
} else {
animating = true;
now = new Date().getTime();
speed = 50;
geoMarker.setStyle(null);
map.getView().setCenter(center);
map.on('postcompose', moveFeature);
map.render();
}
}
// 停止动画
function stopAnimation(ended) {
animating = false;
var coord = ended ? routeCoords[routeLength - 1] : routeCoords[0];
(geoMarker.getGeometry()).setCoordinates(coord);
map.un('postcompose', moveFeature);
}
// 轨迹回放
$('#btn').click(function () {
startAnimation();
})
</script>
</body>
</html>
运行结果如下图所示:
4、实现方式二
第二种实现方式就是利用JavaScript
中的interval
实现,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>轨迹回放</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
<script src="lib/jquery/jquery-3.5.1.min.js"></script>
</head>
<body>
<div id="map" style="width:1200px;height:800px;"></div>
<button id="btn">显示轨迹</button>
<script>
// 获取轨迹点
var points = [];
$.ajax({
type: 'get',
url: 'ashx/GetPointHandler.ashx',
dataType: 'json',
async: false,
cache: false,
success: function (res) {
res.forEach(function (point) {
points.push([point.Longitude, point.Latitude]);
})
}
});
// 创建瓦片图层
var tileLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'tile/{z}/{x}/{y}.png'
})
});
// 创建轨迹点图层
var markerLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 20,
fill: new ol.style.Fill({
color: 'red'
})
})
})
});
// 创建轨迹线图层
var lineLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 5,
color: 'blue'
})
})
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
tileLayer,
markerLayer,
lineLayer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120.0, 30.0],
zoom: 11
})
});
// 定时器
var interval;
var index = 0;
// 显示轨迹
$('#btn').click(function () {
// 清除定时器
if (interval != undefined) {
clearInterval(interval);
}
// 清空要素图层
markerLayer.getSource().clear();
lineLayer.getSource().clear();
index = 0;
// 绘制轨迹线
if (points.length > 1) {
var lineFeature = new ol.Feature({
geometry: new ol.geom.LineString(points)
});
lineLayer.getSource().addFeature(lineFeature);
}
// 创建定时器
interval = setInterval(function () {
if (index < points.length) {
// 清除已有轨迹点
markerLayer.getSource().clear();
// 添加轨迹点
var currentPoint = points[index];
markerFeature = new ol.Feature({
geometry: new ol.geom.Point(currentPoint)
});
markerLayer.getSource().addFeature(markerFeature);
// 索引+1
index++;
} else {
clearInterval(interval);
index = 0;
}
}, 10);
});
</script>
</body>
</html>
运行结果如下图所示: