借用上篇文章中二阶贝塞尔曲线的生成,本文实现mapboxGL中的航线动画。
const from = [101.797439042302, 36.5937248286007];
const to = [106.9733, 35.217];
const points = new ArcLine(from, to);
const line = new Geometry(points, "LineString")
const style = {
version: 8,
sources: {
XYZTile: {
type: "raster",
tiles: [
"http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
"http://webrd02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
"http://webrd03.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
"http://webrd04.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
],
tileSize: 256,
},
LineVector: {
type: "geojson",
data: line,
},
},
layers: [
{
id: "XYZTile",
type: "raster",
source: "XYZTile",
minzoom: 0,
maxzoom: 22,
},
{
id: "LineVector",
type: "line",
source: "LineVector",
paint: {
"line-color": "#f00",
"line-width": 3,
},
},
],
};
const map = new mapboxgl.Map({
container: "map",
style,
attributionControl: false,
center: [104.74329766269716, 35.80025022526921],
zoom: 8,
pitch: 60,
bearing: getAngle(from, to)
});
map.on('load', () => {
// 添加动态图标
map.loadImage('../css/icon.png', function(error, image) {
if (error) throw error
map.addImage('flyline-icon', image)
map.addSource('flyline-point', {
'type': 'geojson',
'data': new Geometry(from, 'Point')
})
map.addLayer({
'id': 'flyline-point',
'source': 'flyline-point',
'type': 'symbol',
'layout': {
'icon-image': 'flyline-icon',
'icon-size': 0.4,
'icon-allow-overlap': true,
'icon-rotation-alignment': 'map',
'icon-pitch-alignment': 'map',
'icon-rotate': 0
}
})
})
const count = 500
const length = turf.length(line)
const interval = length / count
let index = 0
let playFunction = () => {
if(index > count) {
clearInterval(playFlag)
} else {
const point = turf.along(line, index * interval)
const pointP = turf.along(line, index * interval * 0.8)
map.getSource('flyline-point').setData(point)
const rotate = getAngle(pointP.geometry.coordinates, point.geometry.coordinates)
map.setLayoutProperty('flyline-point', 'icon-rotate', rotate)
setView(pointP.geometry.coordinates, rotate + 90)
index++
}
}
let playFlag = setInterval(playFunction)
playFunction()
/ / 设置视图
function setView(center, angle) {
map.setBearing(angle);
map.setCenter(center);
}
// 计算角度
function getAngle(coords1, coords2) {
return turf.bearing(
turf.point(coords1),
turf.point(coords2)
) - 90
}