zhyt1985
1/11/2018 - 4:12 AM

canvasRender支持标签避让测试代码

参考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);
            }