先来看效果图
点击绘制清除地图上的所有聚合,开始绘制轨迹路线,点击销毁清除地图上的轨迹路线,展示聚合,快进快推、开始暂停、回到起点直达终点是轨迹展示的功能组件,主要用于控制巡航器,有需要可以看一下
初始化聚合方法
参考链接: 高德地图官网–点聚合.
initCluster() {
//points就是要展示的一组经纬度
for (var i = 0; i < this.points.length; i += 1) {
this.markers.push(
new AMap.Marker({
position: this.points[i],
content:
'<div style="background-color: hsla(180, 100%, 50%, 0.7); height: 24px; width: 24px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 1px;"></div>',
offset: new AMap.Pixel(-15, -15),
})
);
}
var count = this.markers.length;
var _renderClusterMarker = function (context) {
var factor = Math.pow(context.count / count, 1 / 18);
var div = document.createElement('div');
var Hue = 180 - factor * 180;
var bgColor = 'hsla(' + Hue + ',100%,50%,0.7)';
var fontColor = 'hsla(' + Hue + ',100%,20%,1)';
var borderColor = 'hsla(' + Hue + ',100%,40%,1)';
var shadowColor = 'hsla(' + Hue + ',100%,50%,1)';
div.style.backgroundColor = bgColor;
var size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
div.style.width = div.style.height = size + 'px';
div.style.border = 'solid 1px ' + borderColor;
div.style.borderRadius = size / 2 + 'px';
div.style.boxShadow = '0 0 1px ' + shadowColor;
div.innerHTML = context.count;
div.style.lineHeight = size + 'px';
div.style.color = fontColor;
div.style.fontSize = '14px';
div.style.textAlign = 'center';
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
context.marker.setContent(div);
};
this.cluster = new AMap.MarkerClusterer(this.map, this.markers, {
gridSize: 80,
renderClusterMarker: _renderClusterMarker,
});
},
参考链接: 高德地图官网–轨迹展示.
轨迹展示的方法
drawLine(list) {
this.destroy();
let that = this;
// 清除轨迹路线
if (this.pathSimplifierIns) {
this.pathSimplifierIns.setData([]);
}
that.percentage = 0;
AMapUI.load(
['ui/misc/PathSimplifier', 'lib/$'],
function (PathSimplifier, $) {
if (!PathSimplifier.supportCanvas) {
alert('当前环境不支持 Canvas!');
return;
}
that.pathSimplifierIns = new PathSimplifier({
zIndex: 100,
//autoSetFitView:false,
map: that.map, //所属的地图实例
getPath: function (pathData, pathIndex) {
return pathData.path;
},
getHoverTitle: function (pathData, pathIndex, pointIndex) {
if (pointIndex >= 0) {
//point
return (
pathData.name +
',点:' +
pointIndex +
'/' +
pathData.path.length
);
}
return pathData.name + ',点数量' + pathData.path.length;
},
renderOptions: {
renderAllPointsIfNumberBelow: 100, //绘制路线节点,如不需要可设置为-1
},
});
window.pathSimplifierIns = that.pathSimplifierIns;
//设置数据
that.pathSimplifierIns.setData([
{
name: '路线0',
path: list,
},
]);
that.trackFlag = true;
var navg = that.pathSimplifierIns.createPathNavigator(0, {
loop: false, //循环播放
speed: 10000, //巡航速度,单位千米/小时-默认70,动态设置
dirToPosInMillsecs: 0,
});
var p1 = list[0];
var p2 = list[list.length - 1];
navg.on('move', function () {
let idx = navg.getCursor().idx; //走到了第几个点
let tail = navg.getCursor().tail; //至下一个节点的比例位置
let totalIdx = idx + tail;
var distance = Math.round(
AMap.GeometryUtil.distance(p1, p2) / 1000
);
if (idx === list.length - 1) {
that.isPlay = 1;
that.percentage = 100;
} else {
// 根据走过的距离计算进度(算的是直线距离,不适合弯路)
// that.percentage = Math.round(
// (this.getMovedDistance() / 1000 / distance) * 100
// );
// 根据走过的点数计算进度
that.percentage = parseInt((totalIdx / list.length) * 100);
}
that.latlng = [navg.getPosition().lat, navg.getPosition().lng];
});
that.navg = navg;
}
);
},
清除聚合的方法
destroy() {
if (this.markers) {
this.markers = [];
}
// if (this.cluster) {
// this.cluster = null;
// }
// for (var i = 0; i < this.markers.length; i++) {
// this.cluster.removeMarker(this.markers[i]); //删除单个聚合
// }
// 清除地图上所有聚合
this.cluster.clearMarkers();
},
全部代码(该注释的已经注释,代码可直接复制使用,dataLine是一组经纬度,使用时替换一下就好,如果你们懒得找可以直接找我要)
<template>
<div class="dashboard">
<div id="map"
:style="'height:'+mapHeight+'px'"></div>
<div class="operation">
<el-card class="box-card">
<div slot="header"
class="clearfix">
<span>操作栏</span>
</div>
<el-row class="t-flex t-around">
<div class="textCenter">
<el-button type="success"
icon="el-icon-edit"
@click="draw"
circle></el-button>
<p class="lineH24">绘制</p>
</div>
<div class="textCenter">
<el-button type="primary"
icon="el-icon-arrow-left"
@click="playTrack(0)"
circle></el-button>
<p class="lineH24">快退</p>
</div>
<div class="textCenter"
v-if="isPlay == 1">
<el-button type="info"
icon="el-icon-video-play"
@click="playTrack(1)"
circle></el-button>
<p class="lineH24">开始</p>
</div>
<div class="textCenter"
v-if="isPlay == 2">
<el-button type="success"
icon="el-icon-video-pause"
@click="playTrack(2)"
circle></el-button>
<p class="lineH24">暂停</p>
</div>
<div class="textCenter">
<el-button type="primary"
icon="el-icon-arrow-right"
@click="playTrack(3)"
circle></el-button>
<p class="lineH24">快进</p>
</div>
<div class="textCenter">
<el-button type="warning"
icon="el-icon-aim"
@click="playTrack(4)"
circle></el-button>
<p class="lineH24">回到起点</p>
</div>
<div class="textCenter">
<el-button type="primary"
icon="el-icon-s-promotion"
@click="playTrack(5)"
circle></el-button>
<p class="lineH24">直达终点</p>
</div>
<div class="textCenter">
<el-button type="info"
icon="el-icon-switch-button"
@click="playTrack(6)"
circle></el-button>
<p class="lineH24">销毁</p>
</div>
</el-row>
<el-row>
<el-progress :percentage="percentage"></el-progress>
</el-row>
</el-card>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import dataLine from '@/utils/dataLine.json';
export default {
name: 'Dashboard',
computed: {
...mapGetters(['name']),
},
data() {
return {
trackFlag: false,
map: null,
pathSimplifierIns: null,
mapHeight: document.body.clientHeight - 50,
lineData: [],
// 巡航器移动速度
moveSpeed: 30000,
// 开始暂停快进快推继续结束标识
isPlay: 1,
// 开始暂停标识符
isPause: 0,
latlng: [],
// 巡航器
navg: null,
// 巡航是否结束
isEnd: false,
percentage: 0,
markers: [],
cluster: [],
points: [
[116.405289, 39.904987],
[113.964458, 40.54664],
[111.47836, 41.135964],
[108.949297, 41.670904],
[106.380111, 42.149509],
[103.774185, 42.56996],
[101.135432, 42.930601],
[98.46826, 43.229964],
[95.777529, 43.466798],
[93.068486, 43.64009],
[90.34669, 43.749086],
[87.61792, 43.793308],
],
};
},
methods: {
destroy() {
if (this.markers) {
this.markers = [];
}
// if (this.cluster) {
// this.cluster = null;
// }
// for (var i = 0; i < this.markers.length; i++) {
// this.cluster.removeMarker(this.markers[i]); //删除单个聚合
// }
// 清除地图上所有聚合
this.cluster.clearMarkers();
},
initMap() {
this.map = new AMap.Map('map', {
zoom: 4,
});
let that = this;
this.initCluster();
// 销毁巡航器
},
initCluster() {
for (var i = 0; i < this.points.length; i += 1) {
this.markers.push(
new AMap.Marker({
position: this.points[i],
content:
'<div style="background-color: hsla(180, 100%, 50%, 0.7); height: 24px; width: 24px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 1px;"></div>',
offset: new AMap.Pixel(-15, -15),
})
);
}
var count = this.markers.length;
var _renderClusterMarker = function (context) {
var factor = Math.pow(context.count / count, 1 / 18);
var div = document.createElement('div');
var Hue = 180 - factor * 180;
var bgColor = 'hsla(' + Hue + ',100%,50%,0.7)';
var fontColor = 'hsla(' + Hue + ',100%,20%,1)';
var borderColor = 'hsla(' + Hue + ',100%,40%,1)';
var shadowColor = 'hsla(' + Hue + ',100%,50%,1)';
div.style.backgroundColor = bgColor;
var size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
div.style.width = div.style.height = size + 'px';
div.style.border = 'solid 1px ' + borderColor;
div.style.borderRadius = size / 2 + 'px';
div.style.boxShadow = '0 0 1px ' + shadowColor;
div.innerHTML = context.count;
div.style.lineHeight = size + 'px';
div.style.color = fontColor;
div.style.fontSize = '14px';
div.style.textAlign = 'center';
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
context.marker.setContent(div);
};
this.cluster = new AMap.MarkerClusterer(this.map, this.markers, {
gridSize: 80,
renderClusterMarker: _renderClusterMarker,
});
},
drawLine(list) {
this.destroy();
let that = this;
// 清除轨迹路线
if (this.pathSimplifierIns) {
this.pathSimplifierIns.setData([]);
}
that.percentage = 0;
AMapUI.load(
['ui/misc/PathSimplifier', 'lib/$'],
function (PathSimplifier, $) {
if (!PathSimplifier.supportCanvas) {
alert('当前环境不支持 Canvas!');
return;
}
that.pathSimplifierIns = new PathSimplifier({
zIndex: 100,
//autoSetFitView:false,
map: that.map, //所属的地图实例
getPath: function (pathData, pathIndex) {
return pathData.path;
},
getHoverTitle: function (pathData, pathIndex, pointIndex) {
if (pointIndex >= 0) {
//point
return (
pathData.name +
',点:' +
pointIndex +
'/' +
pathData.path.length
);
}
return pathData.name + ',点数量' + pathData.path.length;
},
renderOptions: {
renderAllPointsIfNumberBelow: 100, //绘制路线节点,如不需要可设置为-1
},
});
window.pathSimplifierIns = that.pathSimplifierIns;
//设置数据
that.pathSimplifierIns.setData([
{
name: '路线0',
path: list,
},
]);
that.trackFlag = true;
var navg = that.pathSimplifierIns.createPathNavigator(0, {
loop: false, //循环播放
speed: 10000, //巡航速度,单位千米/小时-默认70,动态设置
dirToPosInMillsecs: 0,
});
var p1 = list[0];
var p2 = list[list.length - 1];
navg.on('move', function () {
let idx = navg.getCursor().idx; //走到了第几个点
let tail = navg.getCursor().tail; //至下一个节点的比例位置
let totalIdx = idx + tail;
var distance = Math.round(
AMap.GeometryUtil.distance(p1, p2) / 1000
);
if (idx === list.length - 1) {
that.isPlay = 1;
that.percentage = 100;
} else {
// 根据走过的距离计算进度(算的是直线距离,不适合弯路)
// that.percentage = Math.round(
// (this.getMovedDistance() / 1000 / distance) * 100
// );
// 根据走过的点数计算进度
that.percentage = parseInt((totalIdx / list.length) * 100);
}
that.latlng = [navg.getPosition().lat, navg.getPosition().lng];
});
that.navg = navg;
}
);
},
// 播放控制
playTrack(type) {
if (this.trackFlag) {
if (type === 4) {
//回到起点
this.isPlay = 1;
this.navg.destroy();
this.drawLine(this.lineData);
this.navg.setSpeed(this.moveSpeed);
this.percentage = 0;
} else if (type === 6) {
//销毁
this.isPlay = 1;
this.percentage = 0;
this.trackFlag = false;
if (this.lineData.length > 0) {
this.navg.destroy();
}
if (window.pathSimplifierIns) {
this.pathSimplifierIns.setData([]);
// this.map.remove(this.markers)
}
this.$message({
message: '销毁巡航器,清除轨迹路线',
type: 'success',
});
this.initCluster();
} else if (type === 1) {
if (this.isPlay === 1 && !this.isEnd && this.isPause === 1) {
this.navg.resume();
this.navg.setSpeed(this.moveSpeed);
} else {
this.navg.start();
this.isEnd = false;
this.navg.setSpeed(this.moveSpeed);
}
this.$message({
message: '开始巡航',
type: 'success',
});
this.isPlay = 2;
this.isPause = 0;
} else if (type === 2) {
//暂停
this.navg.pause();
this.isPlay = 1;
this.isPause = 1;
this.$message({
message: '暂停巡航',
type: 'warning',
});
} else if (type === 5) {
//回到终点
this.navg.stop();
this.navg.moveToPoint(this.navg.getPathEndIdx());
this.isPlay = 1;
this.isEnd = true;
this.latlng = [
this.lineData[this.lineData.length - 1][0],
this.lineData[this.lineData.length - 1][1],
];
this.$message({
message: '回到终点',
type: 'warning',
});
this.percentage = 100;
} else if (type === 0) {
//快退
if (this.moveSpeed > 10000) {
this.moveSpeed -= 10000;
this.navg.setSpeed(this.navg.getSpeed() - 10000);
this.$message({
message: '×' + this.moveSpeed / 10000,
});
} else {
this.$message({
message: '已经是最低速度!',
type: 'warning',
});
}
} else if (type === 3) {
//快进
if (this.moveSpeed < 50000) {
this.moveSpeed += 10000;
this.navg.setSpeed(this.navg.getSpeed() + 10000);
this.$message({
message: '×' + this.moveSpeed / 10000,
});
} else {
this.$message({
message: '已经是最高速度!',
type: 'warning',
});
}
}
this.playType = type;
} else {
this.$message({
message: '请先绘制轨迹',
type: 'warning',
});
}
},
draw() {
this.drawLine(this.lineData);
},
},
mounted() {
this.initMap();
console.log(dataLine);
this.lineData = dataLine.list;
// this.lineData = [
// [116.405289, 39.904987],
// [113.964458, 40.54664],
// [111.47836, 41.135964],
// [108.949297, 41.670904],
// [106.380111, 42.149509],
// [103.774185, 42.56996],
// [101.135432, 42.930601],
// [98.46826, 43.229964],
// [95.777529, 43.466798],
// [93.068486, 43.64009],
// [90.34669, 43.749086],
// [87.61792, 43.793308],
// ];
},
};
</script>
<style lang="scss" scoped>
#map {
width: 100%;
}
.dashboard {
position: relative;
}
.operation {
position: absolute;
left: 48px;
top: 48px;
width: 720px;
}
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>