I have this map code for MapBox here: How to get click handler on animated canvas dot on MapBox map?
import { useEffect } from 'react'
import * as mapboxgl from 'mapbox-gl'
import locations from 'seeds/sample-location-list.json'
import styles from './Map.module.css'
export default function Map({ scrollable, id, style, onClick }) {
useEffect(() => {
const map = new mapboxgl.Map({
accessToken: '<token>',
container: id ?? 'map',
center: [16.572149246748594, 19.06111670348622],
zoom: 1.5,
style: style ?? 'mapbox://styles/<co>/<style>',
attributionControl: false,
})
// .addControl(new mapboxgl.AttributionControl({
// compact: true
// }), 'top-left')
var size = 120;
// This implements `StyleImageInterface`
// to draw a pulsing dot icon on the map.
var pulsingDot = {
width: size,
height: size,
data: new Uint8ClampedArray(size * size * 4),
context: null,
// When the layer is added to the map,
// get the rendering context for the map canvas.
onAdd: function () {
var 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 () {
var duration = 1000;
var t = (performance.now() % duration) / duration;
var radius = (size / 2) * 0.3;
var outerRadius = (size / 2) * 0.7 * t + radius;
var 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(253, 253, 150,' + (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(253, 253, 150, 1)';
context.strokeStyle = 'rgb(119, 221, 119)';
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;
}
};
if (!scrollable) map.scrollZoom.disable()
map.on('load', function () {
map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });
locations.forEach(location => {
map.addSource(location.id.seed, {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [location.lng, location.lat] // icon position [lng, lat]
},
properties: {},
}
]
}
})
map.addLayer({
'id': location.id.seed,
'type': 'symbol',
'source': location.id.seed,
'layout': {
'icon-image': 'pulsing-dot'
}
});
})
map.on('mousemove', 'earthquakes-viz', (e) => {
// console.log
})
});
if (onClick) map.on('click', onClick)
return () => map.remove()
}, [])
return (
<div id={id ?? "map"} className={styles.map}></div>
)
}
It animates the pulsing of around 20 dots on a map canvas layer. I checked it after some time and it was at 80MB memory usage (my whole React app, of which the map is a small part part), yet my CPU was screaming, fans going off like crazy. How do I fix it so it's not so processor intensive?
from Why is animated MapBox map screaming on the CPU?
No comments:
Post a Comment