Reputation: 47
I have radar raster on my map and i want to show the data color of the radar by the position of the cursor.
I'm trying to get context of a mapbox canvas by map.getCanvas().getContext('2d')
but it returns null.
Is there a way to do that?
Upvotes: 2
Views: 2012
Reputation: 707
Use GL buffer's location rather than mouse's screen coordinates.
As mentioned in the comment on Manish's very good answer, the codepen is not working because it is using the mouse location while it should use the location on the WebGL buffer, as shown below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="initial-scale=1,maximum-scale=1" />
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.css" rel="stylesheet"/>
</head>
<style>
#map canvas {
cursor: crosshair;
}
</style>
<body>
<div
id="map"
style="position: absolute; top: 0px; bottom: 0px; width: 100%;">
</div>
<div
id="colorPicker"
style="height:30px; width:30px; position: absolute; top: 30px; left: 30px; z-index: 999;
border: 3px solid white;">
</div>
<script>
mapboxgl.accessToken =
"pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA";
const map = new mapboxgl.Map({
container: "map",
style: 'mapbox://styles/mapbox/satellite-v9',
zoom: 4,
center: [77.209, 28.6139],
preserveDrawingBuffer: true
});
window.map = map;
map.on("load", () => {
const colorStyle = document.getElementById("colorPicker").style;
map.on("click", e => {
const canvas = map.getCanvas();
const gl = canvas.getContext("webgl") || canvas.getContext("webgl2");
if (gl) {
const data = new Uint8Array(4);
// Canvas width and hwight is what you see on the screen
const canvasWidth = parseFloat(canvas.style.width, 10);
const canvasHeight = parseFloat(canvas.style.height, 10);
// e.point.x and y, specifying the horizontal and vertical pixels read from the lower left corner of the screen
canvasX = e.point.x;
canvasY = e.point.y;
// WenGL buffer is larger than canvas, there
const bufferX = (gl.drawingBufferWidth / canvasWidth * canvasX).toFixed(0);
const bufferY = (gl.drawingBufferHeight / canvasHeight * (canvasHeight - canvasY)).toFixed(0);
gl.readPixels(
bufferX,
bufferY,
1,
1,
gl.RGBA,
gl.UNSIGNED_BYTE,
data
);
const [r, g, b, a] = data;
const color = `rgba(${r}, ${g}, ${b}, ${a})`;
colorStyle.backgroundColor = color;
console.log (`Canvas size (w/h): ${canvasWidth}/${canvasHeight}`);
console.log (`Buffer size (w/h): ${gl.drawingBufferWidth}/${gl.drawingBufferHeight}`);
console.log (`Point on Canvas (x/y): ${canvasX}/${canvasY}`);
console.log (`Point on Buffer (x/y): ${bufferX}/${bufferY}`);
console.log (`Color: ${color}`);
}
});
});
</script>
</body>
</html>
Upvotes: 3
Reputation: 5213
You can obtain the canvas context (webgl) this way and inspect colors.
map.on("mousemove", e => {
const canvas = map.getCanvas();
const gl = canvas.getContext('webgl') || canvas.getContext('webgl2');
if (gl) {
const { point } = e;
const { x, y } = point;
const data = new Uint8Array(4);
const canvasX = x - canvas.offsetLeft;
const canvasY = canvas.height - y - canvas.offsetTop;
gl.readPixels(canvasX, canvasY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data);
const [r, g, b, a] = data;
const color = `rgba(${r}, ${g}, ${b}, ${a})`;
console.log(`Color at (${x}, ${y}) = ${color}`);
}
});
I had to set map option preserveDrawingBuffer
to true
to be able to get pixel values.
const map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/light-v10",
zoom: 4,
center: [77.209, 28.6139],
preserveDrawingBuffer: true
});
This codepen implements a simple color inspector: https://codepen.io/manishraj/full/jONzpzL
Upvotes: 6