从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:
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; } }
效果如下: