mapbox 框架可以在地图上实现动画移动的效果,这种效果用来模拟人行走,或车辆移动都是很好用的。
具体逻辑为:
1、addSource 将需要移动的坐标点作为源先添加进map
2、addLayer 需要移动的图片或marker显示在地图上
3、切割路线为很多个相隔不远的点位组成
4、map.getSource('point').setData(point) 通过不断更新piont点位源数据中的坐标点来不断改变位置,实现移动效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiYXl1MjM4OSIsImEiOiJjbGU2dTJtc2IwOHplM3JtcnljODZqNWszIn0.iszjybKhsIp0AYyfu8sQmg'
const map = new mapboxgl.Map({
container: 'map',
// You can add layers to the predetermined slots within the Standard style basemap.
style: 'mapbox://styles/mapbox/streets-v11', // mapbox官方给出了几种底图可以选择
center: [104.6826114635814, 28.82097174542686], // 默认地图中心位置 宜宾学院
zoom: 17 // 地图缩放级别
})
const geojson = {
'type': 'FeatureCollection',
'features': [
{
"geometry": {
"coordinates": [
[
104.68070521337489,
28.821763271107827
],
[
104.68251002531275,
28.820279087189235
],
[
104.68382875754492,
28.821495063150238
],
[
104.68198292373376,
28.823004875622075
],
[
104.68075614319605,
28.82182382735529
]
],
"type": "LineString"
},
"type": "Feature",
"properties": {}
}
]
}
let newCoord = []
for (let i = 0; i < geojson.features[0].geometry.coordinates.length - 1; i++) {
var from = turf.point(geojson.features[0].geometry.coordinates[i])
var to = turf.point(geojson.features[0].geometry.coordinates[i + 1])
let lDistance = turf.distance(from, to)
let rings = lineMore(from, to, lDistance, 0.0004)
newCoord = newCoord.concat(rings)
}
console.log(newCoord)
const point = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Point',
'coordinates': [
104.68070521337489,
28.821763271107827
]
}
}]
}
map.on('load', () => {
// 先向mapbox加入源数据(geojson数据格式 urban-areas为ID,唯一标记该源数据)
map.addSource('urban-areas', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
"type": "Feature",
"geometry": {
"coordinates": [
[
[
104.68224393266865,
28.820825119811616
],
[
104.68237853175276,
28.820806143131804
],
[
104.68253324334302,
28.820821053380044
],
[
104.68263999433981,
28.820854940301558
],
[
104.68275912226375,
28.820936268867015
],
[
104.68286742037816,
28.82104877327741
],
[
104.68289526846553,
28.82113416811103
],
[
104.68287515595705,
28.821333422448802
],
[
104.68282255401743,
28.82143237174087
],
[
104.68183509950171,
28.822183326112793
],
[
104.68168404453667,
28.822164945238
],
[
104.68153298957174,
28.82207426620606
],
[
104.68144627283152,
28.82203015205387
],
[
104.68134696817822,
28.821940698298548
],
[
104.68130504534406,
28.82174906388728
],
[
104.68130581736818,
28.821644899952986
],
[
104.68134441858416,
28.821514356693072
],
[
104.68200651171475,
28.820943623997778
],
[
104.68224393266865,
28.820825119811616
]
]
],
"type": "Polygon"
},
"properties": {
'color': '#FF0000',
'height': 20
}
},
{
"geometry": {
"coordinates": [
[
[
104.68249981776768,
28.822209737427144
],
[
104.68327453745434,
28.82160047562293
],
[
104.68299946596244,
28.82133219016545
],
[
104.6822274898658,
28.821938871178958
],
[
104.68249981776768,
28.822209737427144
]
]
],
"type": "Polygon"
},
"type": "Feature",
"properties": {
'color': '#9f5f9f',
'height': 40
}
}
]
}
})
map.addSource('line', {
type: 'geojson',
data: geojson
})
// urban-areas源数据加入图层,通过geojson数据里的properties获取color和height实现颜色高度自定义
map.addLayer({
'id': 'urban-areas-fill',
'type': 'fill-extrusion',
'source': "urban-areas",
'paint': {
'fill-extrusion-color': ['get', 'color'], // 获取properties里面的color属性值
'fill-extrusion-height': ['get', 'height'], // 获取properties里面的height属性值
'fill-extrusion-opacity': 0.9, // 透明度
'fill-extrusion-base': 0, // 距离底层地图的距离
}
})
map.addLayer({
type: 'line',
source: 'line',
id: 'line-background',
paint: {
'line-color': 'blue',
'line-width': 6,
'line-opacity': 0.4
}
})
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/cat.png',
(error, image) => {
if (error) throw error
map.addSource('point', {
'type': 'geojson',
'data': point
})
// Add the image to the map style.
map.addImage('cat', image)
map.addLayer({
'id': 'point',
'source': 'point',
'type': 'symbol',
'layout': {
'icon-image': 'cat',
'icon-size': 0.1,
'icon-rotate': ['get', 'bearing'],
// 'icon-rotation-alignment': 'map',
'icon-allow-overlap': true,
'icon-ignore-placement': true
}
})
}
)
})
const steps = newCoord.length
let counter = 0
function animate() {
const start = newCoord[counter]
const end = newCoord[counter + 1]
point.features[0].geometry.coordinates = start
point.features[0].properties.bearing = turf.bearing(
turf.point(start),
turf.point(end)
)
map.getSource('point').setData(point)
if (counter < steps - 2) {
requestAnimationFrame(animate)
}
counter = counter + 1
}
setTimeout(() => {
animate()
}, 2000)
function lineMore(from, to, distance, splitLength) {
var step = parseInt(distance / splitLength)
var leftLength = distance - step * splitLength
var rings = []
var route = turf.lineString([from.geometry.coordinates, to.geometry.coordinates])
for (let i = 1; i <= step; i++) {
let nlength = i * splitLength
let pnt = turf.along(route, nlength)
rings.push(pnt.geometry.coordinates)
}
if (leftLength > 0) {
rings.push(to.geometry.coordinates)
}
return rings
}
</script>
</body>
</html>