参考inmap 四分位标签避让算法(https://github.com/TalkingData/inmap/blob/master/src/worker/helper/Label.js),基于createjs在canvasRender上实现标签避让或隐藏功能。 测试代码,未考虑不同位置标签样式的处理,未对标签按照坐标进行排序。
if(entry.label&&entry.label.text&&entry.label.type=='box'){
var style=L.extend({
fillColor:'white',//填充色
fillOpacity:1,//填充透明度
color:'blue',//边框颜色
opacity:1,//边框透明度
width:2,//边框宽度
textColor:'black',//文本颜色
textFont:'bold 14px Microsoft YaHei',//文本字体
boxHeight:24,//box高度(宽度自适应)
hideBox:false,//是否隐藏背景box
padding:10,//文本左右离box的距离,单位:像素
textAlign:'center',//对齐方式:center文本中心点 left文本左侧,right文本右侧 参考canvas api中的textAlign
offset:[0,0]//偏移量,单位:像素
},options.labelStyle,entry.label.style);
var txt = new createjs.Text();
txt.text=entry.label.text;
txt.color=style.textColor
txt.font=style.textFont;
txt.textAlign=style.textAlign;
txt.textBaseline='middle';
var x = point.x;
var y = point.y;
var bound=txt.getBounds();
var position = 0;
function getBounds(bd) {
var txtBound = txt.getBounds();
var width = txtBound.width;
var height = txtBound.height;
if (!style.hideBox) {
width = txtBound.width + style.padding + style.width * 2;
height = 24
}
switch(position) {
case 0:
x = point.x;
y = point.y;
break;
case 1:
x = point.x - width / 2;
y = point.y - height;
break;
case 2:
x = point.x - width / 2;
y = point.y + height;
break;
case 3:
x = point.x - width;
y = point.y;
break;
}
return bd.setValues(x, y, width, height);
}
var show = true;
var meet = false;
do {
bound = getBounds(bound);
meet = false;
for (var l = 0; l < labels.length; l++) {
var label = labels[l];
if (!label || label.show === false) {
continue;
}
if (label.bound.intersects(bound)) {
meet = true;
position++;
if (position > 3) {
show = false;
meet = false;
}
break;
}
}
} while(meet)
labels.push({
x: x,
y: y,
data: entry.label,
style: style,
bound: bound,
show: show
})
if (!show) {
continue;
}
//console.info(bound);
var container = new createjs.Container();
if(!style.hideBox){
var width=bound.width;
var topLeft={};
if(style.textAlign=='center'){
topLeft.x=x-width/2;
topLeft.y=y-style.boxHeight/2;
}else if(style.textAlign=='left'){
topLeft.x=x-style.padding/2;
topLeft.y=y-style.boxHeight/2;
}else if(style.textAlign=='right'){
topLeft.x=x-width+style.padding/2;
topLeft.y=y-style.boxHeight/2;
}
topLeft.x+=style.offset[0];
topLeft.y+=style.offset[1];
var border = new createjs.Shape();
border.alpha=style.opacity;
border.graphics.setStrokeStyle(style.width).beginStroke(style.color).drawRoundRect(topLeft.x,topLeft.y,width,style.boxHeight,style.boxHeight/4);
this.stage.addChild(border);
var box=new createjs.Shape();
box.alpha=style.fillOpacity;
box.graphics.beginFill(style.fillColor).drawRoundRect(topLeft.x,topLeft.y,width,style.boxHeight,style.boxHeight/4);
box.cursor='pointer';
box.data=_data[id];
box.dataGroupId=id.split('#')[0];
this.stage.addChild(box);
}
txt.x = x+style.offset[0];
txt.y = y+style.offset[1];
txt.data=_data[id];
txt.dataGroupId=id.split('#')[0];
this.stage.addChild(txt);
}