在cesium中创建icon+text类型的标注,并检测标注遮盖

从2维地图转3维地图,越来越发现自己的不足,2维地图的API都是很完善的,使用API就可以实现2维地图的绝大部分功能,但是3维地图API还不是很完善,很多东西都需要基础开发,开发的过程中也可以学到很多。

1.创建icon+text类型的标注

    icon+text类型的标注在地图底图中很常见,但cesium没有现成的API可以使用,其中的billboard也只能以图片的形式创建一个图标。后来想到使用canvas绘制图标+文字的图片,然后传给billboard,试了一下果然可以,这里备忘一下。

//根据图片和文字绘制canvas
function drawCanvas(img,text,fontsize){
    var canvas = document.createElement('canvas');      //创建canvas标签
    var ctx = canvas.getContext('2d');

    ctx.fillStyle = '#99f';
    ctx.font = fontsize + "px Arial";

    canvas.width = ctx.measureText(text).width + fontsize * 2;      //根据文字内容获取宽度
    canvas.height = fontsize * 2; // fontsize * 1.5

    ctx.drawImage(img, fontsize/2,fontsize/2,fontsize,fontsize);

    ctx.fillStyle = '#000';
    ctx.font = fontsize + "px Calibri,sans-serif";
    ctx.shadowOffsetX = 1;    //阴影往左边偏,横向位移量
    ctx.shadowOffsetY = 0;   //阴影往左边偏,纵向位移量
    ctx.shadowColor = "#fff"; //阴影颜色
    ctx.shadowBlur = 1; //阴影的模糊范围
    ctx.fillText(text, fontsize*7/4, fontsize*4/3);
    return canvas;
}

效果如下:

    

2.检测标注遮盖

1步骤中创建了icon+text类型的标注,但是如果创建大量标注,放缩时难免会出现标注相互遮盖的情况,这样既影响美观也会遮盖住地图信息,这里需要检测标注间的遮盖,显示和不显示一些标注。

由于每个billboard都有对应的中心点(cartesian3世界坐标类型)、高度(height)、宽度(width),我们将中心点转成屏幕坐标,再根据高度宽度也就获得了这个billboard在屏幕上的范围矩形,再去判断矩形相交问题。

于是我们去遍历标注集合(billboardCollection),先设定第一个用于判断矩形相交的对象constB,然后用下一个billboard去跟constB判断相交问题,如果矩形相交,隐藏被比较的billboard;如果矩形不相交,显示被比较的billboard,然后重新设定constB为改被比较的billboard。再用下一个billboard去跟constB判断,这点类似于冒泡算法,直至遍历完成整个标注集合。

整体看起来有点麻烦,但效率还行。

遍历billboardCollection:

扫描二维码关注公众号,回复: 1128636 查看本文章
var len = billboardCollection.length;
var constantB = billboardCollection.get(0);
instantB.show = true;
for (var i = 0; i < len; ++i) {
	if(i>0){
		if(isCollsionWithRect(constantB,billboardCollection.get(i))){	//是否相交	
			billboardCollection.get(i).show = false;
		}else{
			billboardCollection.get(i).show = true;
			constantB = billboardCollection.get(i);
		}
	}
}

检测碰撞:

var b1 = {x : 100,y : 100,width : 80,height : 100};	//矩形左下角的xy值
var b2 = {x : 160,y : 180,width : 100,height : 130};
    
//检测标注碰撞
function isCollsionWithRect(b1,b2){
	var x1 = b1.x,y1 = b1.y,w1 = b1.width*3,h1 = b1.height*3;
	var x2 = b2.x,y2 = b2.y,w2 = b2.width*3,h2 = b2.height*3;		
	if (x1 >= x2 && x1 >= x2 + w2) {
		return false;
	} else if (x1 <= x2 && x1 + w1 <= x2) {
		return false;
	} else if (y1 >= y2 && y1 >= y2 + h2) {
		return false;
	} else if (y1 <= y2 && y1 + h1 <= y2) {
		return false;
	}else{
		return true;
	}
}

效果如下:

                    

猜你喜欢

转载自blog.csdn.net/u014529917/article/details/79523231