此前使用了 vue-baidu-map,由于业务需求不断迭代,该组件已经无法满足我的需求,并且源码本身就存在缺陷以及缺少维护,因此我选择改为使用百度地图js api。
百度地图js api最新版为3.0,另外有GL版,官方给出的说明是:GL版本接口基本向下兼容,迁移成本低。目前v1.0版本支持了基本的3D地图展示、基本地图控件和覆盖物。 但是我实测v_3.0和v_GL似乎并不是完整的向下兼容,这里我使用了 v2.0。
需求如下:
public/index.html
// 同步加载
<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=您的密钥"></script>
// 异步加载
<script type="text/javascript">
function initialize() {
var mp = new BMapGL.Map('map');
mp.centerAndZoom(new BMapGL.Point(121.491, 31.233), 11);
}
function loadScript() {
var script = document.createElement("script");
script.src = "https://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥&callback=initialize";
document.body.appendChild(script);
}
window.onload = loadScript;
</script>
map.vue
<template>
<div>
<v-card class="overflow-hidden">
<div id="bmap"></div>
<v-navigation-drawer v-model="textTrack" :right="true" absolute width="400px">
<time-line></time-line>
</v-navigation-drawer>
</v-card>
</div>
</template>
<script lang='ts'>
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
@Component
export default class Map extends Vue {
private textTrack: boolean = false; // 文字轨迹开关
}
time-line.vue
<template>
<v-card-text class="py-0">
<h3 v-if="!show" style="margin: 3rem 0;">暂无数据</h3>
<v-timeline v-else align-top dense style="text-align: left;">
<v-timeline-item color="primary" small v-for="(item, index) in timelineList" :key="index">
<v-row class="pt-1">
<v-col cols="3">
<strong>{{ tp(item.ts) }}</strong>
</v-col>
<v-col>
<strong>
{{ item.addr ? JSON.parse(`${item.addr}`)[0]['district'] : '-'}}
<span>{{ `(停留${fl(item.stay)})` }}</span>
</strong>
<div class="caption">{{ item.addr ? JSON.parse(`${item.addr}`)[0]['name'] : '-'}}</div>
</v-col>
</v-row>
</v-timeline-item>
</v-timeline>
</v-card-text>
</template>
<script lang='ts'>
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import axios from "axios";
import bus from "@/utils/bus";
@Component
export default class TimeLine extends Vue {
show: boolean = false;
timelineList: any = [];
events: any = [];
input: any = null;
nonce: any = 0;
get timeline() {
return this.events.slice();
}
tp: any = function (timestamp: any, type?: any) {
var date = new Date(Number(timestamp) * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
var Y = date.getFullYear() + "-";
var M =
(date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
function zeroH(h: number) {
return h < 10 ? "0" + h + ":" : h + ":";
}
function zeroM(m: number) {
return m < 10 ? "0" + m + ":" : m + ":";
}
function zeroS(s: number) {
return s < 10 ? "0" + s : s;
}
var D = date.getDate() + " ";
var h = zeroH(date.getHours());
var m = zeroM(date.getMinutes());
var s = zeroS(date.getSeconds());
if (type === 'full') {
return Y + M + D + h + m + s;
} else {
return h + m + s;
}
}
comment() {
const time = new Date().toTimeString();
this.events.push({
id: this.nonce++,
text: this.input,
time: time.replace(
/:\d{2}\sGMT-\d{4}\s\((.*)\)/,
(match, contents, offset) => {
return ` ${contents
.split(" ")
.map((v: any) => v.charAt(0))
.join("")}`;
}
)
});
this.input = null;
}
fl(num: number): any {
if (num / 3600 < 1) {
return `${Math.abs(Math.floor(num / 60))}分${Math.abs(
Math.floor(num % 60)
)}秒`;
} else {
return `${Math.abs(Math.floor(num / 3600))}时${Math.abs(
Math.floor(Math.floor(num % 3600) / 60)
)}分${Math.abs(Math.floor(num % 60))}秒`;
}
}
deduplication(data: any): any {
let _arr: any = [];
data.forEach((item: any, index: number) => {
if (index == 0) {
item.stay = 0;
_arr.push(item);
} else if (index > 0) {
try {
item.stay = 0;
if (
JSON.parse(item.addr)[0].name !=
JSON.parse(data[index - 1].addr)[0].name
) {
_arr.push(item);
console.log("写入" + index);
} else {
_arr[_arr.length - 1].stay +=
Number(item.ts) - Number(data[index - 1].ts);
console.log("重复" + index);
}
} catch (error) {
console.log(error);
}
}
});
return _arr;
}
mounted() {
bus.$on("list", (data: any) => {
this.timelineList = this.deduplication(data);
// .reverse();
if (data.length > 0) {
this.show = true;
}
console.log(data);
});
}
}
</script>
<style lang="scss" scoped>
</style>