I’m trying to integrate a simple map in my Vue.js app following the plusing dot example.
I’ve copied the code into my app like this:
<template>
<div id="mapContainer" class="basemap"></div>
</template>
<script>
import maplibregl from 'maplibre-gl';
export function drawpulsingDot(map, lng, lat) {
// https://maplibre.org/maplibre-gl-js-docs/example/add-image-animated/
let size = 100
if (map.hasImage('stationDot')) map.removeImage('stationDot')
if (map.getLayer('stationDot')) map.removeLayer('stationDot')
if (map.getSource('stationDot')) map.removeSource('stationDot')
const pulsingDot = {
width: size,
height: size,
data: new Uint8Array(size * size * 4),
// When the layer is added to the map,
// get the rendering context for the map canvas.
onAdd: function () {
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
this.context = canvas.getContext('2d');
},
// Call once before every frame where the icon will be used.
render: function () {
const duration = 1000;
const t = (performance.now() % duration) / duration;
const radius = (size / 2) * 0.3;
const outerRadius = (size / 2) * 0.7 * t + radius;
const context = this.context;
// Draw the outer circle.
context.clearRect(0, 0, this.width, this.height);
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
outerRadius,
0,
Math.PI * 2
);
context.fillStyle = `rgba(255, 200, 200, ${1 - t})`;
context.fill();
// Draw the inner circle.
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
radius,
0,
Math.PI * 2
);
context.fillStyle = 'rgba(255, 100, 100, 1)';
context.strokeStyle = 'white';
context.lineWidth = 2 + 4 * (1 - t);
context.fill();
context.stroke();
// Update this image's data with data from the canvas.
this.data = context.getImageData(
0,
0,
this.width,
this.height
).data;
// Continuously repaint the map, resulting
// in the smooth animation of the dot.
map.triggerRepaint();
// Return `true` to let the map know that the image was updated.
return true;
}
};
map.addImage('stationDot', pulsingDot, {pixelRatio: 2});
map.addSource('stationDot', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [lng, lat]
}
}
]
}
});
map.addLayer({
'id': 'stationDot',
'type': 'symbol',
'source': 'stationDot',
'layout': {
'icon-image': 'stationDot'
}
});
}
export default {
name: "BaseMap",
data() {},
mounted() {
this.map = new maplibregl.Map({
container: 'mapContainer',
style: 'https://api.maptiler.com/maps/voyager-v2/style.json?key=Q0mHUPCTF6KhlmRpN11W',
center: [15, 53],
zoom: 3.6
})
this.map.on('click', async e => {
drawpulsingDot(this.map, e.lngLat.lng, e.lngLat.lat)
})
},
methods: {}
}
</script>
<style scoped>
</style>
The thing is, when the pulsing dot is being rendered it uses 100% of by CPU, either on Chromium or Firefox.
Is there something wrong with using this library with Vue.js ? Is there a way to lower the GPU/CPU load for such a small animation ?
I’ve the issue with both maplibre and mapbox.
Thanks