添加动画图像
向地图添加动画图像;
<!DOCTYPE html>
<html lang="en">
<head>
<title>添加动画图像</title>
<meta property="og:description" content="向地图添加动画图像" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style:
'https://demotiles.maplibre.org/styles/osm-bright-gl-style/style.json',
center: [0, 0],
zoom: 1
});
// 使用通用的浏览器图像API添加一个脉冲点动画
const size = 200;
// 这种实现使用2个单独的动画帧,
// 每一个都在Canvas 2D环境中绘制,然后组合成一个帧。
// 然后,每一帧都上传到具有增量ID的地图中。
function getPulsingDot() {
// 创建Canvas
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const context = canvas.getContext('2d');
// 在我们的脉冲圆中使用动态数据渲染
// 而不是立即将图像添加到地图,
// 因为我们需要在添加到地图之前使图像动起来
const render = () => {
// 动画循环
context.clearRect(0, 0, size, size);
// 根据当前时间绘制一个脉冲圆圈
const duration = 1000;
const t = (performance.now() % duration) / duration;
const radius = (size / 2) * 0.3;
const outerRadius = (size / 2) * 0.7 * t + radius;
const context2 = canvas.getContext('2d');
// 外圈
const gradient = context2.createRadialGradient(
size / 2,
size / 2,
radius,
size / 2,
size / 2,
outerRadius
);
gradient.addColorStop(0, `rgba(255, 200, 200, 1)`);
gradient.addColorStop(1, `rgba(255, 0, 0, 0)`);
context2.fillStyle = gradient;
context2.beginPath();
context2.arc(size / 2, size / 2, outerRadius, 0, Math.PI * 2);
context2.fill();
// 内圈
context2.beginPath();
context2.arc(size / 2, size / 2, radius, 0, Math.PI * 2);
context2.fillStyle = 'rgba(255, 0, 0, 1)';
context2.strokeStyle = 'white';
context2.lineWidth = 2 + 4 * (1 - t);
context2.fill();
context2.stroke();
// 更新图像源为新图像
if (map.hasImage('pulsing-dot')) {
map.updateImage('pulsing-dot', canvas);
} else {
map.addImage('pulsing-dot', canvas, {pixelRatio: 2});
}
// 请求下一帧
map.triggerRepaint();
requestAnimationFrame(render);
};
// 开始渲染
requestAnimationFrame(render);
}
map.on('load', () => {
getPulsingDot();
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
},
'properties': {
'title': '赤道上的一点'
}
}
]
}
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'pulsing-dot'
}
});
});
</script>
</body>
</html>