在leaflet当中提供了几个轨迹回放的插件,该文将用两个插件分别实现一下轨迹回放
leaflet-trackplayer
安装依赖&准备静态资源
轨迹回放使用leaflet-trackplayer插件
npm i leaflet-trackplayer --force
初始化地图,在这里初始化地图可以参考,然后导入了轨迹回放插件和一个图片(用于标记当前轨迹运动点)图片资源
import L from 'leaflet';
import 'leaflet-trackplayer';
import 'leaflet/dist/leaflet.css';
import CAR from '@/assets/image/car.png';
let map = null;
const sourceUrl = 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png';
map = L.map('map').setView([23, 120], 2);
const tileLayer = L.tileLayer(sourceUrl, {
maxZoom: 18,
minZoom: 2,
attribution: '© modify'
});
tileLayer.addTo(map);
准备轨迹数据 轨迹数据
const path = [
{
lat: 34.25615548523744,
lng: 108.91164044842363
},
// ...... 省略了很多点,可以在上面GitHub链接中获取
{
lat: 34.29496736180883,
lng: 108.91578701078069
}
];
轨迹绘制&播放
- 先定义一个icon,用来标记轨迹运动点
- 通过
new L.TrackPlayer
创建轨迹,入参分别是 轨迹数据、轨迹配置。然后直接加到地图当中即可,并且我们保存返回的track对象 - 最后通过track对象的start方法开启播放,通过pause方法关闭播放
let track = null;
const initPath = () => {
// 定义沿着轨迹移动的Icon
let markerIcon = L.icon({
iconSize: [27, 54],
iconUrl: CAR, // 前面导入的img资源
iconAnchor: [13.5, 27]
});
// 创建播放器对象并添加至地图
track = new L.TrackPlayer(path,
// 轨迹配置,都可以不要,保留markerIcon一个就可以了
{
markerIcon,
speed: 500, // 播放速度
weight: 10, // 轨迹线宽度
passedLineColor: '#f2cac9', // 已行驶轨迹部分的颜色
notPassedLineColor: '#fbeee2', // 未行驶轨迹部分的颜色
panTo: true, // 地图跟随移动
// 轨迹箭头样式
polylineDecoratorOptions: {
patterns: [
/**
* offset 第一个图案符号的偏移量,从线的起点开始。默认值:0
* endOffset 最后一个图案符号的最小偏移量,从线的端点开始。默认值:0
* repeat 重复间隔。定义每个连续符号的锚点之间的距离
* symbol 图标样式
* */
{
offset: 0,
repeat: 20,
symbol: L.Symbol.arrowHead({
pixelSize: 10,
pathOptions: {color: 'red', weight: 2, stroke: true}
})
}
]
},
markerRotation: true // 是否开启marker的旋转
}
).addTo(map);
track.start();
// 停止播放
// track.pause();
// 清除轨迹
// track.remove();
};
通过滑块控制轨迹进度
通过track的progress事件去得到轨迹运动过程当中的值,其中progress就是进度(0-1之间)。只需要去取progress的值去给到el-slider绑定的值就完成了滑块进度对应轨迹进度效果了,同时我们给滑块添加@input
事件(使用鼠标拖曳时,活动过程实时触发)。在这个方法当中再通过track.setProgress
重新设置值回去也就完成了进度条控制轨迹的效果了
const sliderProgress = ref(0);
// 监听进度 progress 0-1 index 到第几个点
track.on('progress', (progress, {lng, lat}, index) => {
sliderProgress.value = progress * 100;
console.log(`progress:${progress.toFixed(2)} - position:${lng.toFixed(2)},${lat.toFixed(2)} - trackIndex:${index}`);
});
const formatTooltip = (val) => {
return val.toFixed(2);
};
const changeProgress = (val) => {
track.setProgress(val / 100);
track.setSpeed(500);
};
<el-slider v-model="sliderProgress" :format-tooltip="formatTooltip" @input="changeProgress"/>
同理还可以控制speed运动速度,通过track.setSpeed(val)
去设置。这里默认取500km/h的速度值,而后切换的时候根据500去乘对应的倍数将速度设置回去即可
const selectSpeed = ref(1);
const options = [
{
value: 0.5,
label: 'X0.5'
},
{
value: 1,
label: 'X1'
},
{
value: 2,
label: 'X2'
},
{
value: 3,
label: 'X3'
},
{
value: 5,
label: 'X5'
}
];
const changeSpeed = (val) => {
track.setSpeed(500 * val);
};
<el-select v-model="selectSpeed" @change="changeSpeed">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
leaflet-plugin-trackplayback
npm i leaflet-plugin-trackplayback
使用这个插件还需要注意一下版本,其中leaflet-plugin-trackplayback版本是1.0.5,这个时候leaflet用最新的1.9.4会报错
Cannot use 'in' operator to search for '_leaflet_id' in undefined
。这个时候将leaflet版本降到1.7.0即可。——20240625记录,后续版本升级可能会修复吧
轨迹运动数据准备&初始化
这里每一个运动轨迹组(相当于一个数组)每个数组包含以下几个字段,
-
lng 经度
-
lat 纬度
-
time 时间戳,表示什么时间到该点
-
dir 偏移 0-360之间
-
info 鼠标移入该点展示的内容(表格),格式是key+value。可以看插件渲染的逻辑,直接遍历取key和value值构建table
_getTooltipText: function (targetobj) { let content = [] content.push('<table>') if (targetobj.info && targetobj.info.length) { for (let i = 0, len = targetobj.info.length; i < len; i++) { content.push('<tr>') content.push('<td>' + targetobj.info[i].key + '</td>') content.push('<td>' + targetobj.info[i].value + '</td>') content.push('</tr>') } } content.push('</table>') content = content.join('') return content },
初始化轨迹
const data = [
[
{
'lng': 104.93071666666665,
'lat': 34.679016666666665,
'time': 1502120041,
'dir': 16,
'info': []
},
{
'lng': 105.23038333333334,
'lat': 35.3806,
'time': 1502151540,
'dir': 254,
'info': []
},
{
'lng': 105.13055,
'lat': 36.379416666666664,
'time': 1502158560,
'dir': 173,
'info': []
},
{
'lng': 104.12878333333334,
'lat': 37.37925,
'time': 1502164364,
'dir': 235,
'info': []
},
{
'lng': 103.23196666666665,
'lat': 38.37178333333333,
'time': 1502164715,
'dir': 152,
'info': []
},
{
'lng': 104.9536,
'lat': 39.33618333333333,
'time': 1502165384,
'dir': 158,
'info': [
{key: 'name', value: 'zhang san'},
{key: 'age', value: '18'},
{key: 'sex', value: 'men'},
{key: 'address', value: 'anywhere'}
]
}
]
];
// 入参 轨迹数据、地图对象、配置。通过start方法开始运动
const trackplayback = L.trackplayback(data, map, {})
trackplayback.start()
配置说明
GitHub地址 options配置的源码位置:node_modules/leaflet-plugin-trackplayback/src/leaflet.trackplayback/draw.js & clock.js
{
// 时间运动配置
clockOptions: {
// 播放速度
// 计算方法 fpstime * Math.pow(2, this._speed - 1)
speed: 12,
// 最大播放速度
maxSpeed: 65
},
// info弹框配置
toolTipOptions: {
offset: [0, 0],
direction: 'left',
permanent: false
},
// 运动过程中点配置
targetOptions: {
useImg: true, // 使用图片
imgUrl: './ship.png', // 图片地址
color: '#00f', // 边框色
fillColor: '#9FD12D' // 填充色
},
// 远动中经过点配置
trackPointOptions: {
isDraw: true, // 是否绘制
useCanvas: true, // 使用canvas
stroke: true, // 边框
color: '#ef0300', // 边框色
fill: true, // 填充
fillColor: '#ef0300', // 填充色
opacity: 1, // 透明度
radius: 4 // 半径
},
// 轨迹线配置
trackLineOptions: {
isDraw: true, // 是否绘制
stroke: true, // 边框
color: '#ff4', // 线色
weight: 2, // 线宽
opacity: 1 // 透明度
// fill: true, // 轨迹点之间的填充
// fillColor: '#000' // 填充色
}
}
API说明
也就是拿到trackplayback对象之后调用对应的方法获取到对应的值,然后我们可以切换速度去控制运动快慢,以及切换时间控制运动到那个点。
// 设置时间,从这个时间开始运动
// trackplayback.setCursor(1502164364);
// 获取当前时间(运动过程中)、开始时间、结束时间
// trackplayback.getCurTime();
// trackplayback.getStartTime();
// trackplayback.getEndTime();
// 获取速度
// let speed = trackplayback.getSpeed();
// 隐藏、显示轨迹线
// trackplayback.hideTrackLine();
// trackplayback.showTrackLine();
// 隐藏、显示轨迹点
// trackplayback.hideTrackPoint();
// trackplayback.showTrackPoint()
// 改变速度。重绘轨迹 isPlaying 是否在播放 返回boolean类型
// trackplayback.setSpeed(15);
// trackplayback.rePlaying();
// 暂停轨迹
// trackplayback.stop();
// 销毁轨迹
// trackplayback.dispose();
完整实例
最后贴一下完整的代码示例,替换该文件node_modules/leaflet-plugin-trackplayback/examples/1.html
运行该html
<html lang="zh-cn">
<head>
<title>leaflet.trackplayback</title>
<link rel="stylesheet" href="./lib/leaflet/leaflet.css">
<script src="./lib/leaflet/leaflet.js"></script>
<script src="../dist/leaflet.trackplayback.js"></script>
</head>
<body>
<div id='mapId'
style=" position: absolute; left: 0; top: 0; right: 0; bottom: 0; width: 100%; height: 100%; overflow: hidden;"></div>
<script>
const data = [];
const map = L.map('mapId').setView([33.74, 104.38], 6);
L.tileLayer('https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png').addTo(map);
const trackplayback = L.trackplayback(data, map, {
clockOptions: {
// 播放速度
// 计算方法 fpstime * Math.pow(2, this._speed - 1)
speed: 12,
// 最大播放速度
maxSpeed: 65
},
toolTipOptions: {
offset: [0, 0],
direction: 'left',
permanent: false
},
// 运动过程中点配置
targetOptions: {
useImg: true, // 使用图片
imgUrl: './ship.png', // 图片地址
color: '#00f', // 边框色
fillColor: '#9FD12D' // 填充色
},
// 远动中经过点配置
trackPointOptions: {
isDraw: true, // 是否绘制
useCanvas: true, // 使用canvas
stroke: true, // 边框
color: '#ef0300', // 边框色
fill: true, // 填充
fillColor: '#ef0300', // 填充色
opacity: 1, // 透明度
radius: 4 // 半径
},
// 轨迹线配置
trackLineOptions: {
isDraw: true, // 是否绘制
stroke: true, // 边框
color: '#ff4', // 线色
weight: 2, // 线宽
opacity: 1 // 透明度
// fill: true, // 轨迹点之间的填充
// fillColor: '#000' // 填充色
}
});
trackplayback.start();
</script>
</body>
</html>