vue3-openlayers 轨迹回放(历史轨迹),实时轨迹
本篇介绍一下使用vue3-openlayers轨迹回放(历史轨迹),实时轨迹
1 需求
- 轨迹回放(历史轨迹)
- 实时轨迹
2 分析
可以使用和上一篇相同的办法,即主要是利用定时器,不断添加feature
- 轨迹回放(历史轨迹),一般是一次性拿到所有坐标点,按照时间间隔不断循环添加feature
- 实时轨迹,一般是通过websocket监听,不断获取最新坐标点,根据上报的频率,可能需要抽样
也可以使用ol-animation-path(下篇介绍,其实openlayers也有类似的方法)
3 实现
<template>
<ol-map
:loadTilesWhileAnimating="true"
:loadTilesWhileInteracting="true"
style="width: 100%; height: 100%"
ref="mapRef"
>
<ol-view
ref="view"
:center="center"
:zoom="zoom"
:projection="projection"
/>
<ol-tile-layer>
<ol-source-tianditu
layerType="img"
:projection="projection"
:tk="key"
:hidpi="true"
ref="sourceRef"
></ol-source-tianditu>
</ol-tile-layer>
<ol-tile-layer>
<ol-source-tianditu
:isLabel="true"
layerType="img"
:projection="projection"
:tk="key"
:hidpi="true"
></ol-source-tianditu>
</ol-tile-layer>
<ol-vector-layer>
<ol-source-vector>
<ol-feature v-if="trace.length" >
<ol-geom-point :coordinates="trace[trace.length-1][1]" ></ol-geom-point>
<ol-style>
<ol-style-icon :src="iconSrc" :width="30" :height="30" :rotation="angle"></ol-style-icon>
</ol-style>
</ol-feature>
<ol-feature v-for="(item, index) in trace" :key="index">
<ol-geom-line-string :coordinates="item"></ol-geom-line-string>
<ol-style>
<ol-style-stroke color="rgba(228, 147, 87, 1)" :width="3"></ol-style-stroke>
</ol-style>
</ol-feature>
</ol-source-vector>
</ol-vector-layer>
</ol-map>
</template>
<script setup lang="ts">
import iconSrc from '@/assets/image/truck.png';
const center = ref([121, 31]);
const projection = ref('EPSG:4326');
const zoom = ref(5);
const mapRef = ref();
const key = '替换为天地图key';
const sourceRef = ref(null);
const data = ref([
[110, 30],
[110.2, 30],
[110.4, 30.2],
[110.8, 30.4],
[111, 31],
[111.3, 31],
[111.6, 31],
[111.9, 31],
[112, 31],
[112.3, 31],
[112.5, 31],
[112.8, 31],
[113, 31],
[114, 31],
[115.3, 32],
[115.5, 32],
[115.8, 31.8],
[116, 31.4],
[116.2, 31.1],
[116.5, 30.5],
[115, 30.2],
[114, 29.8],
[113, 29.6],
[112, 29.4],
[111, 30.2],
[110, 30.4],
[109, 30.6],
[108, 31]
]);
const trace = ref([]);
const angle=ref(0);
onMounted(() => {
let i = 0;
const interval = setInterval(() => {
if (data.value[i + 1]) {
let arc = 0;
if (
(data.value[i + 1][0] - data.value[i][0] >= 0 &&
data.value[i + 1][1] - data.value[i][1] >= 0) ||
(data.value[i + 1][0] - data.value[i][0] < 0 &&
data.value[i + 1][1] - data.value[i][1] > 0)
) {
arc = Math.atan(
(data.value[i + 1][0] - data.value[i][0]) / (data.value[i + 1][1] - data.value[i][1])
);
} else if (
(data.value[i + 1][0] - data.value[i][0] > 0 &&
data.value[i + 1][1] - data.value[i][1] < 0) ||
(data.value[i + 1][0] - data.value[i][0] < 0 &&
data.value[i + 1][1] - data.value[i][1] < 0)
) {
arc =
Math.PI +
Math.atan(
(data.value[i + 1][0] - data.value[i][0]) /
(data.value[i + 1][1] - data.value[i][1])
);
}
angle.value=arc
trace.value.push([data.value[i], data.value[i + 1]]);
i++;
} else {
clearInterval(interval);
}
}, 200);
});
</script>
<style scoped lang="scss">
.overlay-content {
background: rgba(255, 255, 255, 0.7);
box-shadow: 0 5px 10px rgb(2 2 2 / 20%);
padding: 10px 20px;
font-size: 16px;
color: black;
}
</style>