<!--Index.vue-->
<template>
<div
:id="mapId"
:style="{height,width}"
></div>
</template>
<script>
/**
*@ 实时动态轨迹, 直接单车多车同时实时动态运行
*/
import { initMap } from './mapUtils';
/*
[116.418757,39.917544], // 北京
[116.366794,39.915309], //西城区
[116.637122,40.324272], //怀柔区
[117.164143,39.120474], // 南开区
[116.286968,39.863642], // 丰台区
*/
export default {
name: 'RealTimeTrack',
props: {
mapId: {
required: false,
type: String,
default: 'real-time-track'
},
width: {
required: false,
type: String,
default: '500px'
},
height: {
required: false,
type: String,
default: '500px'
},
/*
positionConfig : {
carId1:{
position:[],
},
carId2:{
position:[],
}
}
*/
positionConfig: {
required: true,
type: Object
}
},
data() {
return {
map: null,
navigator: null,
config: null,
saveQueue: [],
curIdx: -1
};
},
watch: {
positionConfig: {
handler(newV) {
this.saveQueue.push(newV);
},
deep: true
}
},
mounted() {
this.config = this.positionConfig;
initMap(this);
},
methods: {
pathLineClick(data) {
this.$emit('pathLineClick', data);
},
toListen() {
// 排除网路延时造成的速度错误影响
this.navigator.on('pause', () => {
this.curIdx++;
this.config = this.saveQueue[this.curIdx];
this.navigator.expandPath();
});
}
}
};
</script>
/* eslint-disable */
import CreateNvg from './cnvg';
const initData = (data) => {
let list = [];
Object.values(data).forEach((item, index) => item.id = index);
for (let carId in data) {
list.push({
id: data[carId].id,
name: carId,
path: data[carId].position,
...data[carId],
stopStatus: false
});
}
return list;
};
export const initMap = (vm) => {
vm.map = new AMap.Map(vm.mapId, {
zoom: 5
});
AMapUI.load(['ui/misc/PathSimplifier', 'lib/$'], function(PathSimplifier, $) {
if (!PathSimplifier.supportCanvas) {
alert('当前环境不支持 Canvas!');
return;
}
var emptyLineStyle = {
lineWidth: 0,
fillStyle: null,
strokeStyle: null,
borderStyle: null
};
var pathSimplifierIns = new PathSimplifier({
zIndex: 10000,
// autoSetFitView: false,
map: vm.map, // 所属的地图实例
getPath: function(pathData, pathIndex) {
return pathData.path;
},
getHoverTitle: function(pathData, pathIndex, pointIndex) {
return null;
},
renderOptions: {
//将点、线相关的style全部置emptyLineStyle
pathLineStyle: emptyLineStyle,
pathLineSelectedStyle: emptyLineStyle,
pathLineHoverStyle: emptyLineStyle,
keyPointStyle: emptyLineStyle,
startPointStyle: emptyLineStyle,
endPointStyle: emptyLineStyle,
keyPointHoverStyle: emptyLineStyle,
keyPointOnSelectedPathLineStyle: emptyLineStyle
// renderAllPointsIfNumberBelow: 100 // 绘制路线节点,如不需要可设置为-1
}
});
pathSimplifierIns.on('pathClick pointClick', function(e, info) {
//info.pathData 即是相关的轨迹数据,如果info.pointIndex >= 0,则表示由轨迹上的节点触发
vm.pathLineClick(info);
});
const config = initData(vm.config);
pathSimplifierIns.setData(config);
vm.navigator = new CreateNvg(config, pathSimplifierIns, PathSimplifier);
vm.toListen();
});
};
<!--cnvg.js-->
export default class CreateNvg {
constructor(config, pathSimplifierIns, PathSimplifier) {
this.config = config;
this.listens = {};
this.endIdx = 0; // 只需要考虑最长路程节点的
this.id = [];
this.cursor = [];
this.status = [];
this.navigatorList = [];
this.pathSimplifierIns = pathSimplifierIns;
this.PathSimplifier = PathSimplifier;
this.init();
}
initData() {
this.id = this.config.map(item => item.id);
this.cursor = new Array(this.config.length);
this.status = new Array(this.config.length);
}
init() {
this.initData();
this.pathSimplifierIns.setData(this.config);
this.expandPath();
// this.createNavigation();
this.navigatorList.forEach((navigator) => {
navigator.start();
});
}
reStart() {
this.config.forEach(item => {
item.stopStatus = false;
});
}
isEnd() {
return this.config.every(item => item.stopStatus);
}
on(type, cb) {
this.listens[type] = cb;
}
emit(type) {
this.listens[type]();
}
expandPath() {
this.navigatorList.forEach((navigator, index) => {
navigator.on('pause', () => {
this.config[index].stopStatus = true;
if (this.isEnd()) {
this.emit('pause');
this.reStart();
return;
}
});
});
if (this.canExpand()) {
setTimeout(() => {
this.expandPath();
});
}
}
canExpand() {
this.endIdx++;
if (this.endIdx >= this.getMaxLen()) {
this.endIdx--; // 保证正常续航
return false;
}
this.handleCursor();
this.handleStatus();
this.pathSimplifierIns.setData(this.config); // 延展路径
// 重新建立一个巡航器
this.createNavigation();
this.doStart();
this.doMoveTo();
return true;
}
createNavigation() {
this.config.forEach((item, index) => {
const { pathNavigatorStyle, pathLinePassedStyle, pathLinePassedHidden, id, speed } = item;
this.navigatorList[index] = this.pathSimplifierIns.createPathNavigator(id, {
speed: speed.v || 100, // km/h // 适合汽车
pathNavigatorStyle: {
width: (pathNavigatorStyle && pathNavigatorStyle.width) || 16,
height: (pathNavigatorStyle && pathNavigatorStyle.height) || 32,
content: this.PathSimplifier.Render.Canvas.getImageContent(
(
pathNavigatorStyle && pathNavigatorStyle.content) || 'https://webapi.amap.com/ui/1.1/ui/misc/PathSimplifier/examples/imgs/car.png',
pathNavigatorStyle && pathNavigatorStyle.onload,
pathNavigatorStyle && pathNavigatorStyle.onerror
),
strokeStyle: null,
fillStyle: null,
pathLinePassedStyle: pathLinePassedHidden ? {} : (
pathLinePassedStyle ? {
lineWidth: pathLinePassedStyle.lineWidth || 5,
strokeStyle: pathLinePassedStyle.strokeStyle || '#3F9DCC',
borderStyle: pathLinePassedStyle.borderStyle || '#ccc'
} : {
lineWidth: 5,
strokeStyle: '#3F9DCC',
borderStyle: '#ccc'
}
)
}
});
});
}
getMaxLen() {
const sortData = this.config.sort((p, c) => c.path.length - p.path.length);
return (sortData[0] && sortData[0].path && sortData[0].path.length) || 0;
}
handleCursor() {
this.navigatorList.forEach((navigator, index) => {
this.cursor[index] = navigator.getCursor().clone(); // 保存巡航器的位置
});
}
handleStatus() {
this.navigatorList.forEach((navigator, index) => {
this.status[index] = navigator.getNaviStatus();
});
}
doStart() {
this.status.forEach((state, index) => {
if (state !== 'stop') {
this.navigatorList[index].start();
}
});
}
doMoveTo() {
this.cursor.forEach((cursor, index) => {
if (cursor.idx >= 0) {
this.navigatorList[index].moveToPoint(cursor.idx, cursor.tail);
}
});
}
}