D3:饼图标签带有"水平结尾" - 线没有重叠

时间:2014-05-17 16:45:32

标签: javascript d3.js label lines

我非常喜欢带有线条的David Buezas饼图,特别是那些水平线,因为它们提高了可读性:http://bl.ocks.org/dbuezas/9306799。但标签在那里重叠,也可能是线条。

偶然发现http://blog.safaribooksonline.com/2014/03/11/solving-d3-label-placement-constraint-relaxing/(包含很多小提琴,对不起,发布链接的声誉不足),这解释了如何避免重叠。尝试使用这个示例来修改带有&#34;水平结尾&#34;的行,基本上将<line>替换为<polyline>,但是失败了。

  • 看来<line>的输出与<polyline>的输出不同,因为我复制了所有属性,但它的绘制方式不同(很确定我没有做过)搞砸了)

  • 在Bueza的例子中,我显然不知道如何将线条切成文字。以为我可以通过以下方式解决方法:

    • <line>替换为<polyline>
    • 将属性从<line>复制到<polyine>的点属性
    • 只需执行<polyline>
    • ,即可向last x-value + 30添加直线水平线的属性
    • 然后使用transform

    • 以某种方式调整文本
    • 除了比Bueza的例子更不优雅之外,我也不介意人们不知道水平线是否需要向左或向右(标签)可以在图表的两边)。

任何人都可以

  • 告诉我为什么<line>的输出与<polyline>不同?
  • 制作那个&#34; Slice to text&#34; -buezas的例子对新手来说更清楚一点?

这是我的尝试:http://jsfiddle.net/HdwTH/40/

非常感谢。

1 个答案:

答案 0 :(得分:2)

来自this answer的方法可以解决这个问题,尤其是以下几行(感谢很多Lars提示)。

/* check whether the default position 
       overlaps any other labels*/
    var conflicts = [];
    labelLayout.visit(function(node, x1, y1, x2, y2){
        //recurse down the tree, adding any overlapping labels
        //to the conflicts array

        //node is the node in the quadtree, 
        //node.point is the value that we added to the tree
        //x1,y1,x2,y2 are the bounds of the rectangle that
        //this node covers

        if (  (x1 > d.r + maxLabelWidth/2) 
                //left edge of node is to the right of right edge of label
            ||(x2 < d.l - maxLabelWidth/2) 
                //right edge of node is to the left of left edge of label
            ||(y1 > d.b + maxLabelHeight/2)
                //top (minY) edge of node is greater than the bottom of label
            ||(y2 < d.t - maxLabelHeight/2 ) )
                //bottom (maxY) edge of node is less than the top of label

              return true; //don't bother visiting children or checking this node

        var p = node.point;
        var v = false, h = false;
        if ( p ) { //p is defined, i.e., there is a value stored in this node
            h =  ( ((p.l > d.l) && (p.l <= d.r))
               || ((p.r > d.l) && (p.r <= d.r)) 
               || ((p.l < d.l)&&(p.r >=d.r) ) ); //horizontal conflict

            v =  ( ((p.t > d.t) && (p.t <= d.b))
               || ((p.b > d.t) && (p.b <= d.b))  
               || ((p.t < d.t)&&(p.b >=d.b) ) ); //vertical conflict

            if (h&&v)
                conflicts.push(p); //add to conflict list
        }

    });

    if (conflicts.length) {
        console.log(d, " conflicts with ", conflicts);  
        var rightEdge = d3.max(conflicts, function(d2) {
            return d2.r;
        });

        d.l = rightEdge;
        d.x = d.l + bbox.width / 2 + 5;
        d.r = d.l + bbox.width + 10;
    }
    else console.log("no conflicts for ", d);

    /* add this label to the quadtree, so it will show up as a conflict
       for future labels.  */
    labelLayout.add( d );
    var maxLabelWidth = Math.max(maxLabelWidth, bbox.width+10);
    var maxLabelHeight = Math.max(maxLabelHeight, bbox.height+10);

以下是工作解决方案的小提琴:http://jsfiddle.net/Qh9X5/1249/