需求:
一张图片的rgba值中存储了一些有用信息
把这个图片在cesium和openlayers中分别加载
在地图上点击图片,希望拿到点击处图片的颜色值
分析:
cesium和openlayers都是基于<canvas>来构建的gis引擎
cesium使用的三维
//gl是WebGLRenderingContext类型
let gl=canvas.getContext("webgl")
openlayers使用的是二维
//ctx是CanvasRenderingContext2D类型
let ctx=canvas.getContext("2d")
那么问题就转换为gl和ctx中是否有相关方法来实现
实现:
gl、ctx中都有根据canvas的屏幕坐标来拿到对应像素信息和颜色信息的方法
这样就脱离了cesium、openlayers框架来实现这个功能!
canvas维度 | 如何拿到具体坐标的颜色值 | API参考文档 |
---|---|---|
3d | gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); 其中pixels包含rgba的值 | WebGLRenderingContext.readPixels() - Web API 接口参考 | MDN |
2d | let res = ctx.getImageData(x, y, 1, 1).data; 上述res是[r,g,b,a]形式的数组对象 | CanvasRenderingContext2D.getImageData() - Web API 接口参考 | MDN |
canvas 3维中来获取
canvas.onmousedown = function (ev) {
var x = ev.clientX;
var y = ev.clientY;
var rect = ev.target.getBoundingClientRect();
if (
rect.left <= x &&
x < rect.right &&
rect.top <= y &&
y < rect.bottom
) {
var x_in_canvas = x - rect.left;
var y_in_canvas = rect.bottom - y;
var pixels = new Uint8Array(4);
draw();
//根据点击值,获取对应点击位置的颜色值
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
let red = pixels[0];
let green = pixels[1];
let blue = pixels[2];
let alpha = pixels[3];
console.log(pixels);
}
};
上述代码用到的draw()方法很关键,代码如下:
function draw() {
//没有下述2句,图像存在,但是gl.readPixels()拿到的值都是0
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //没有这1句,背景会消失
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0); //没有这1句,则矩形消失
}
canvas 2维中来获取
//鼠标点击事件
canvasDom.onmousedown = function (ev) {
var x = ev.clientX;
var y = ev.clientY;
var rect = ev.target.getBoundingClientRect();
if (
rect.left <= x &&
x < rect.right &&
rect.top <= y &&
y < rect.bottom
) {
//根据点击值,获取对应点击位置的颜色值
let res = ctx.getImageData(x, y, 1, 1).data;
let red = res[0];
let green = res[1];
let blue = res[2];
let alpha = res[3];
console.log(res);
}
};
备注:
一个 dom对象,不可能既为2d、又为webgl
当通过getContext(“webgl”)拿到webgl对象后
是无法再对同一个canvas dom对象执行getContext("2d")来拿到2d对象的!!
demo下载:
注意:demo中的canvas2d.html,是为了验证双canvas遮挡,依然可以正确取值
所以看到上面的是红色canvas,我实际上取的是下面蓝色的canvas