D3:饼式标签的“水平”尾线没有重叠

D3: pie labels with "horizontal ending"-lines without overlapping

本文关键字:重叠 水平 标签 D3      更新时间:2023-09-26

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

偶然发现http://blog.safaribooksonline.com/2014/03/11/solving-d3-label-placement-constraint-relaxing/(包含很多麻烦,抱歉,没有足够的声誉张贴链接),它解释了如何避免重叠。试图适应这个例子,以"水平结束"标记行,基本上是用<polyline>代替<line>,但失败了。

  • 它看起来像<line>会有不同的输出比<polyline>,因为我复制了所有的属性,但它绘制不同(很确定我没有搞砸)

  • 我显然不明白在Bueza的例子中,这些行是如何被切成文本的。我想我可以做一个变通:

    • <polyline>代替<line>
    • <line>的属性复制到<polyine>的点属性
    • 添加属性,绘制一条直线,水平线<polyline>通过简单地做last x-value + 30
    • 然后用transform

    • 调整文本
    • 除了这比Bueza的例子差得多之外,我也不介意人们不知道水平线是向左还是向右(标签可以在图表的两侧)。

谁能来帮我一下

  • 告诉我为什么<line>的输出和<polyline>不同?
  • 让"切片到文本"的东西从Buezas的例子对新手更清楚一点?

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

这个答案的方法奏效了,尤其是下面的几行(非常感谢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/