问题:最近遇到一个需求,在mapbox项目中开启rgb地形时,需要拾取点位并弹窗展示相关信息,最开始点位绘制采取circle的方案,发现在拾取时存在bug,有时能拾取到,有时又拾取不到;
解决:最后采用symbol图层的方式加载点位解决,用canvas画出点位并保存为png加载到mapbox中,使用symbol图层加载,就能100%正常拾取了。
//使用canvas的方式绘制圆形图标
function _drawCircle({
radius,
color,
strokeColor,
strokeWidth,
}: {
radius: number;
color: string;
strokeWidth: number;
strokeColor: string;
}): string {
const pixelRatio = window.devicePixelRatio || 1;
const canvas = document.createElement('canvas');
const size = (radius + strokeWidth) * 2 + 5;
canvas.width = canvas.height = size * pixelRatio;
canvas.style.width = canvas.style.height = `${size}px`;
const context = canvas.getContext('2d');
if (context) {
context.scale(pixelRatio, pixelRatio);
const centerX = radius + strokeWidth / 2;
const centerY = radius + strokeWidth / 2;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI);
context.fillStyle = color;
context.strokeStyle = strokeColor;
context.lineWidth = strokeWidth;
context.fill();
context.stroke();
const dataURL = canvas.toDataURL('image/png');
return dataURL;
}
return '';
}
//将绘制的图标加载到mapbox实例中
_addImages() {
const circle = this._drawCircle({
radius: 10,
color: 'red',
strokeColor: 'yellow',
strokeWidth: 3
});
this.map.loadImage(circle as any, (err, image) => {
if (err) throw err;
this.map.addImage('circle', image as any);
});
}
//最后以symbol图层的方式加载点位
map.addLayer({
id,
type: 'symbol',
source,
layout: {
'icon-image': 'circle',
'icon-size': 0.6,
'icon-allow-overlap': true
}
});
总结:推测使用circle方式绘制的点位实际是贴在球体上,没有高度,因此当mapbox场景中加入地形后,点位虽然显示在表面上,但实际的位置并没有变动。而使用symbol方式加载的点位图标始终面向屏幕,因此拾取的判断更加简单而准确。