如何在地图框上获取像素的颜色



我的地图上有雷达光栅,我想通过光标的位置显示雷达的数据颜色。

雷达示例

我正在尝试通过map.getCanvas().getContext('2d')获取地图框画布的上下文,但它返回 null。

有没有办法做到这一点?

您可以通过这种方式获取画布上下文 (webgl( 并检查颜色。

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}`);
}
});

我必须将地图选项preserveDrawingBuffer设置为true才能获得像素值。

const map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/light-v10",
zoom: 4,
center: [77.209, 28.6139],
preserveDrawingBuffer: true
});

此代码笔实现了一个简单的颜色检查器:https://codepen.io/manishraj/full/jONzpzL

使用 GL 缓冲区的位置,而不是鼠标的屏幕坐标。

正如在对 Manish 非常好的答案的评论中提到的,代码笔不起作用,因为它正在使用鼠标位置,而它应该使用 WebGL 缓冲区上的位置,如下所示:

<!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>