最终的样子
+
mapboxgl 官网的例子 :
https://docs.mapbox.com/mapbox-gl-js/example/animate-a-line/
turf.js 官网:
http://turfjs.org/
requestAnimationFrame 详解 我觉得写的很好:
https://www.jianshu.com/p/fa5512dfb4f5
一、实现思路
1、绘制线
2、绘制一个点,将线的第一个点赋值给点
3、将geometry中线的每个节点值 赋值给点
<template>
<div class="hello">
<div id="map" style="width: 100%; height: 100%"></div>
</div>
</template>
<script>
export default {
name: "Map",
data() {
return {};
},
methods: {
initmap() {
mapboxgl.accessToken =
"pk.eyJ1IjoiMTU5MzU3MyIsImEiOiJjamw3bW85dHkwbXlvM3ZzMm5iZnZ6bWJpIn0.W6_MGVjNaImIybFdMJBMpg";
let initMap = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
zoom: 3, //缩放层级
center: [108.420679, 36.772537], //进入后展现的中心点
});
return initMap;
},
},
mounted() {
window.map = this.initmap();
let coor = [
[74.91932166254529, 43.34799143293915],
[78.82968043376917, 35.32100587068976],
[82.20680846345789, 43.283329636323145],
[84.60634680034286, 35.46590128939705],
[88.60557736181482, 42.82877118912947],
[92.07157718176103, 34.07894110138169],
[100.86988441701243, 42.95898883351077],
[109.31270449123406, 31.766651099437112],
[127.53142149351078, 41.17789211364973],
[135.8853697774751, 33.33965831774536],
[142.3730104660895, 43.283329636323145],
[148.94952294496136, 37.39631064993182],
[152.94875350643326, 44.753129575870986],
];
let origin = coor[0];
var route = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: coor,
},
},
],
};
var point = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: origin,
},
},
],
};
map.on("load", function () {
map.addSource("route", {
type: "geojson",
data: route,
});
map.addSource("point", {
type: "geojson",
data: point,
});
map.addLayer({
id: "route",
source: "route",
type: "line",
paint: {
"line-width": 2,
"line-color": "#007cbf",
},
});
map.addLayer({
id: "point",
source: "point",
type: "symbol",
layout: {
"icon-image": "airport-15",
"icon-rotate": ["get", "bearing"],
"icon-rotation-alignment": "map",
"icon-allow-overlap": true,
"icon-ignore-placement": true,
},
});
console.log(map, map.getStyle(), "map");
let that = this;
var steps = 10000;
var counter = 0;
function animate() {
debugger;
if (counter == coor.length) {
cancelAnimationFrame(requestAnimationFrame(animate));
point.features[0].geometry.coordinates = [];
point.features[0].geometry.coordinates = origin;
map.getSource("point").setData(point);
counter = -1;
} else {
point.features[0].geometry.coordinates = coor[counter];
if (counter < coor.length - 1) {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 1 : counter]),
turf.point(coor[counter >= steps ? counter : counter + 1])
);
} else {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 3 : counter - 2]),
turf.point(coor[counter >= steps ? counter - 2 : counter - 1])
);
}
if (point.features[0].properties.bearing != 0) {
console.log(map, map.getSource("point"), "map", point);
console.log(map.getStyle(), map.getSource("point"), "map", point);
map.getSource("point").setData(point);
}
}
counter++;
requestAnimationFrame(animate);
}
animate(counter);
});
},
};
</script>
<style scoped>
.hello {
width: 100%;
height: 100%;
}
</style>
是不是很快,原因是我们数据的节点很少,我们需要将线的细化,这里用到的是 turf.lineChunk 转之后发现他不是标准的geometry 线数据
<template>
<div class="hello">
<div id="map" style="width: 100%; height: 100%"></div>
</div>
</template>
<script>
export default {
name: "Map",
data() {
return {};
},
methods: {
initmap() {
mapboxgl.accessToken =
"pk.eyJ1IjoiMTU5MzU3MyIsImEiOiJjamw3bW85dHkwbXlvM3ZzMm5iZnZ6bWJpIn0.W6_MGVjNaImIybFdMJBMpg";
let initMap = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
zoom: 3, //缩放层级
center: [108.420679, 36.772537], //进入后展现的中心点
});
return initMap;
},
},
mounted() {
window.map = this.initmap();
let coor_old = [
[74.91932166254529, 43.34799143293915],
[78.82968043376917, 35.32100587068976],
[82.20680846345789, 43.283329636323145],
[84.60634680034286, 35.46590128939705],
[88.60557736181482, 42.82877118912947],
[92.07157718176103, 34.07894110138169],
[100.86988441701243, 42.95898883351077],
[109.31270449123406, 31.766651099437112],
[127.53142149351078, 41.17789211364973],
[135.8853697774751, 33.33965831774536],
[142.3730104660895, 43.283329636323145],
[148.94952294496136, 37.39631064993182],
[152.94875350643326, 44.753129575870986],
];
let route = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: coor_old,
},
},
],
};
let routelineChunk = turf.lineChunk(route.features[0], 50, {
units: "miles",
});
// 将转好后的geometry拼接成正常的数据
let coor = [];
routelineChunk.features.forEach((el) => {
el.geometry.coordinates.forEach((yo) => {
coor.push(yo);
});
});
route.features[0].geometry.coordinates = coor;
let origin = coor[0];
let point = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: origin,
},
},
],
};
map.on("load", function () {
map.addSource("route", {
type: "geojson",
data: route,
});
map.addSource("point", {
type: "geojson",
data: point,
});
map.addLayer({
id: "route",
source: "route",
type: "line",
paint: {
"line-width": 2,
"line-color": "#007cbf",
},
});
map.addLayer({
id: "point",
source: "point",
type: "symbol",
layout: {
"icon-image": "airport-15",
"icon-rotate": ["get", "bearing"],
"icon-rotation-alignment": "map",
"icon-allow-overlap": true,
"icon-ignore-placement": true,
},
});
let that = this;
let steps = 10000;
let counter = 0;
function animate() {
debugger;
if (counter == coor.length) {
cancelAnimationFrame(requestAnimationFrame(animate));
point.features[0].geometry.coordinates = [];
point.features[0].geometry.coordinates = origin;
map.getSource("point").setData(point);
counter = -1;
} else {
point.features[0].geometry.coordinates = coor[counter];
if (counter < coor.length - 1) {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 1 : counter]),
turf.point(coor[counter >= steps ? counter : counter + 1])
);
} else {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 3 : counter - 2]),
turf.point(coor[counter >= steps ? counter - 2 : counter - 1])
);
}
if (point.features[0].properties.bearing != 0) {
map.getSource("point").setData(point);
}
}
counter++;
requestAnimationFrame(animate);
}
animate(counter);
});
},
};
</script>
<style scoped>
.hello {
width: 100%;
height: 100%;
}
</style>
线的数据是一样的,移动的数据是空的,我们将每次都push更新数据
最终的代码
<template>
<div class="hello">
<div id="map" style="width: 100%; height: 100%"></div>
</div>
</template>
<script>
export default {
name: "Map",
data() {
return {};
},
methods: {
initmap() {
mapboxgl.accessToken =
"pk.eyJ1IjoiMTU5MzU3MyIsImEiOiJjamw3bW85dHkwbXlvM3ZzMm5iZnZ6bWJpIn0.W6_MGVjNaImIybFdMJBMpg";
let initMap = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
zoom: 3, //缩放层级
center: [108.420679, 36.772537], //进入后展现的中心点
});
return initMap;
},
},
mounted() {
window.map = this.initmap();
let coor_old = [
[74.91932166254529, 43.34799143293915],
[78.82968043376917, 35.32100587068976],
[82.20680846345789, 43.283329636323145],
[84.60634680034286, 35.46590128939705],
[88.60557736181482, 42.82877118912947],
[92.07157718176103, 34.07894110138169],
[100.86988441701243, 42.95898883351077],
[109.31270449123406, 31.766651099437112],
[127.53142149351078, 41.17789211364973],
[135.8853697774751, 33.33965831774536],
[142.3730104660895, 43.283329636323145],
[148.94952294496136, 37.39631064993182],
[152.94875350643326, 44.753129575870986],
];
let route = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: coor_old,
},
},
],
};
let routeMove = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: [],
},
},
],
};
let speed = 50; // 运行速度
let routelineChunk = turf.lineChunk(route.features[0], speed, {
units: "miles",
});
// 将转好后的geometry拼接成正常的数据
let coor = [];
routelineChunk.features.forEach((el) => {
el.geometry.coordinates.forEach((yo) => {
coor.push(yo);
});
});
route.features[0].geometry.coordinates = coor;
let origin = coor[0];
let point = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: origin,
},
},
],
};
map.on("load", function () {
map.addSource("route", {
type: "geojson",
data: route,
});
map.addSource("routeMove", {
type: "geojson",
data: routeMove,
});
map.addSource("point", {
type: "geojson",
data: point,
});
map.addLayer({
id: "route",
source: "route",
type: "line",
paint: {
"line-width": 10,
"line-color": "#F22C2C",
"line-opacity": 0.3,
},
layout: {
"line-cap": "round",
"line-join": "round",
},
});
map.addLayer({
id: "routeMove",
source: "routeMove",
type: "line",
paint: {
"line-width": 2,
"line-color": "#007cbf",
"line-opacity": 1,
},
layout: {
"line-cap": "round",
"line-join": "round",
},
});
map.addLayer({
id: "point",
source: "point",
type: "symbol",
layout: {
"icon-image": "airport-15",
"icon-rotate": ["get", "bearing"],
"icon-rotation-alignment": "map",
"icon-allow-overlap": true,
"icon-ignore-placement": true,
},
});
let that = this;
let steps = 10000;
let counter = 0;
function animate() {
if (counter == coor.length) {
cancelAnimationFrame(requestAnimationFrame(animate));
point.features[0].geometry.coordinates = [];
point.features[0].geometry.coordinates = origin;
map.getSource("point").setData(point);
counter = -1;
routeMove.features[0].geometry.coordinates = [];
} else {
// 移动添加点数据
point.features[0].geometry.coordinates = coor[counter];
if (counter < coor.length - 1) {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 1 : counter]),
turf.point(coor[counter >= steps ? counter : counter + 1])
);
} else {
point.features[0].properties.bearing = turf.bearing(
turf.point(coor[counter >= steps ? counter - 3 : counter - 2]),
turf.point(coor[counter >= steps ? counter - 2 : counter - 1])
);
}
if (point.features[0].properties.bearing != 0) {
map.getSource("point").setData(point);
}
// 添加线数据
routeMove.features[0].geometry.coordinates.push(coor[counter]);
map.getSource("routeMove").setData(routeMove);
}
counter++;
requestAnimationFrame(animate);
}
animate(counter);
});
},
};
</script>
<style scoped>
.hello {
width: 100%;
height: 100%;
}
</style>
这个最后可以拓展就可以实现, keep 上面的轨迹了
版权声明:本文为xm_w_xm原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。