【问题标题】:D3: pie labels with "horizontal ending"-lines without overlappingD3:带有“水平结尾”的饼图标签 - 线条不重叠
【发布时间】:2014-05-17 16:45:32
【问题描述】:

我非常喜欢带线条的 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 示例中的线条是如何切割成文本的。以为我可以通过以下方式解决问题:

    • <line> 替换为<polyline>
    • <line> 中的属性复制到<polyine> 的点属性中
    • 通过简单地执行last x-value + 30 来为<polyline> 添加绘制一条水平直线的属性
    • 然后通过变换以某种方式调整文本

    • 除了这比 Bueza 的示例优雅得多之外,我也不介意人们不知道水平线是需要向左还是向右(标签可能位于图表)。

有人可以吗

  • 告诉我为什么 <line> 的输出与 <polyline> 不同?
  • 让 Buezas 示例中的“切片到文本”——对于新手来说更清楚一点?

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

非常感谢。

【问题讨论】:

  • 你所说的“崩溃”是什么意思?你的意思是重叠吗?
  • 是的。这显然不清楚,我改变了它。谢谢拉斯。
  • 如果我理解正确,This questionthis question 会做同样的事情。

标签: javascript d3.js label lines


【解决方案1】:

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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    相关资源
    最近更新 更多