1、需求
数据库中有设备的经纬度记录,前端需要实现从数据库中取到数据后在地图上显示轨迹,显示轨迹的方式就是一个一个点地有序显示。点与点之间用线段连接,最终构成一条轨迹线。
2、场景过程
- 前端定义一个播放暂停按钮;
- 点击播放时,定时器开启;
- 播放阶段,每隔1秒打一个坐标锚点,超过1个点时,点与点之间进行线段连接;
- 点击暂停时,停止打点和绘制线段;
- 再点击播放时,接着上述暂停时的锚点继续开始新的坐标锚点绘制和线段绘制;
- 播放完数据,停止打点和线段绘制。
3、实现思路
旧的实现思路,采用定时器的开启、暂停来实现,找了相关资料,未发现有很好的例子。
基于Vue2,考虑到其带有监听器的功能,如果监听打点数的数值发生变化,就往地图上赛锚点和线段。岂不是一种简约的实现方式。
4、实现代码
<template>
<div style="width: 100%; height: 100%">
<!-- 工具条 -->
<div class="map_box">
<el-form :inline="true" :model="form">
<el-button @click="onStart" :type=" isStart ? 'success':'primary'" >
<svg-icon :icon-class="isStart ? 'stop':'start'" />
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 地图 -->
<div class="amap-container">
<el-amap view-mode="3D" :center="center" :zoom="zoom" map-style="amap://styles/d6bf8c1d69cea9f5c696185ad4ac4c86">
<!--轨迹 -->
<el-amap-polyline :editable="polyline.editable"
:visible="polyline.visible"
:stroke-weight="2"
:stroke-color="polyline.strokeColor"
:draggable="polyline.draggable"
:path="polyline.path"></el-amap-polyline>
<!--标注 -->
<el-amap-layer-labels>
<el-amap-label-marker v-for="(marker, index) in markers"
:key="index"
:visible="true"
:position="marker.position"
:text="marker.text"
:icon="marker.icon"></el-amap-label-marker>
</el-amap-layer-labels>
</el-amap>
</div>
</div>
</template>
<script>
export default {
data(){
return{
center: [105.602725,37.076636],
zoom:5,
pointData:[],
markers:[],
polyline:{
editable: false,
visible: false,
draggable: false,
path:[],
strokeColor: "#f10303"
},
isStart: false,
isPause: true,
playTimer: null,
playCount:1,
playSpeed: 500
}
},
created() {
},
methods:{
getData(){
//this.pointData数据源
},
//计时打点
addMarker(){
//只有一个点打点后结束
if (this.isPause){
let marker = this.pointData[this.playCount - 1]
//锚点打点
this.markers.push(marker)
this.center = marker.position
//轨迹打点
this.polyline.path.push(marker.position)
this.polyline.visible = true
//缩放地图倍数
this.zoom = 14
this.isPause = false
}
if (this.pointData.length === 1){
return false
}
//开启计时器
if (this.pointData.length > 1){
let that = this
this.playTimer = setInterval(()=>{
that.playCount++
},this.playSpeed)
}
},
onStart(){
this.isStart = !this.isStart
if (this.isStart){
//加载一次数据
if (this.isPause){
this.getData()
}
this.addMarker()
}else {
//清除计时器
if (this.playCount <= this.pointData.length){
clearInterval(this.playTimer)
this.playTimer = null
this.tableScroll()
}
}
}
},
watch:{
playCount: {
handler(newValue, oldValue) {
if (newValue > this.pointData.length) {
clearInterval(this.playTimer)
this.playTimer = null
this.isPause = true
} else {
let position = this.pointData[newValue - 1].position
this.markers.push(this.pointData[newValue - 1])
this.polyline.path.push(position)
this.center = position
}
}
}
}
}
</script>
<style scoped>
/deep/ .amap-container{
width: 100%;
height: 100%;
top: 0.5%;
bottom: 0.5%;
border-radius: 15px;
}
.map_box{
position: absolute;
top: 1.5%;
right: 0.5%;
z-index: 66666;
}
.table-class{
position: absolute;
top: 12%;
right: 1%;
z-index: 66666;
}
</style>
5、思考
- 做功能时,尽量使用已有的功能,借助基础力量达到四两拨千斤的作用;
- 多思考Vue2的框架的特点,结合特点进行使用。