简体   繁体   English

D3圆圈包布局中的圆圈文字

[英]Text along circles in a D3 circle pack layout

I am trying to label some circles in a circle pack layout with text that flows along the circle itself. 我试图在circle pack layout标记一些圆圈,文本沿着圆圈本身流动。

Here is one experimental jsfiddle : 这是一个实验性的jsfiddle

在此输入图像描述

As you can see, it is possible to render text along the circle, centered at its top. 如您所见,可以沿着圆圈渲染文本,以其顶部为中心。 Though browser's rendering of curved SVG text is terrible. 虽然浏览器的曲线SVG文本渲染很糟糕。 But let's say we don't care about it. 但是,让我们说我们不关心它。

Here is another jsfiddle 这是另一个jsfiddle

在此输入图像描述

I would like to place curved labels on this graph, under these conditions: 在这些情况下,我想在此图表上放置弯曲标签:

  • The circle represents a province (only depth==1) (BRITISH COLUMBIA, ALBERTA, and so forth) 圆圈代表一个省(只有深度== 1)(不列颠哥伦比亚省,阿尔伯塔省,等等)
  • The sum of sizes of all children (in other words, number of parliament seats allotted) of the province is greater than 5. 所有儿童的规模总和(换句话说,分配的议会席位数)大于5。
  • The name of the province should be all UPPERCASE. 该省的名称应该都是大写的。

You can see some of my attempts in the code itself. 您可以在代码本身中看到我的一些尝试。 I have been trying for hours. 我已经尝试了几个小时。 My main problem is that circles in the circle are now somewhere in XY space, whereas, in the first jsfiddle, all circles have centers in coordinate system origin. 我的主要问题是圆圈中的圆圈现在位于XY空间中的某个位置,而在第一个jsfiddle中,所有圆圈都具有坐标系原点的中心。

Maybe you can help me by taking a fresh look at this. 也许你可以通过重新审视来帮助我。

Underlying data is based on this table: 基础数据基于此表:

在此输入图像描述

(NOTE: This is somewhat related to the question 'Circle packs as nodes of a D3 force layout' I asked the other day, however this is an independent experiment.) (注意:这与我前几天询问的'圆形包作为D3力布局的节点'的问题有些相关,但这是一个独立的实验。)

I decided to use regular SVG arcs instead of d3.svg.arc(). 我决定使用常规SVG弧而不是d3.svg.arc()。 I still think it is a right decision. 我仍然认为这是一个正确的决定。 However, here is what I have now: :) jsfiddle 但是,这就是我现在拥有的::) jsfiddle

在此输入图像描述

NOTE (since I am answering my question): If some of you already spent time on this problem and found another solution, please post it, and I will accept your answer. 注意(因为我正在回答我的问题):如果你们中的一些人已经花时间解决这个问题并找到了另一个解决方案,请发布它,我会接受你的回答。 Thanks to @FernOfTheAndes for participating in process of finding this solution, as it was filled with pain and misery of working with svg arcs. 感谢@FernOfTheAndes参与找到这个解决方案的过程,因为它充满了与svg弧一起工作的痛苦和痛苦。

Here is jsfiddle of the solution: 这是解决方案的jsfiddle

在此输入图像描述

As mentioned in comments, the key part was generating arcs as plain vanilla svg arcs, not via d3.svg.arc(). 正如评论中所提到的,关键部分是产生弧形作为普通的香草svg弧,而不是通过d3.svg.arc()。

SVG rules for defining arcs are clear, but a little hard to manage. 用于定义弧的SVG规则很明确,但有点难以管理。 Here is an interactive explorer of svg syntax for arcs . 这是一个用于弧的svg语法的交互式资源管理器

Also, these two functions helped me during this process of defining the right arcs: 此外,这两个函数在定义正确弧线的过程中帮助了我:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
    var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
    return {
        x: centerX + (radius * Math.cos(angleInRadians)),
        y: centerY + (radius * Math.sin(angleInRadians))
    };
}

function describeArc(x, y, radius, startAngle, endAngle){
    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);
    var arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
    var d = [
        "M", start.x, start.y, 
        "A", radius, radius, 0, 1, 1, end.x, end.y
    ].join(" ");
    return d;       
}

This is the code that actually directly generates curved labels: 这是实际直接生成弯曲标签的代码:

var arcPaths = vis.append("g")
    .style("fill","navy");
var labels = arcPaths.append("text")
    .style("opacity", function(d) {
        if (d.depth == 0) {
            return 0.0;
        }
        if (!d.children) {
            return 0.0;
        }
        var sumOfChildrenSizes = 0;
        d.children.forEach(function(child){sumOfChildrenSizes += child.size;});
        //alert(sumOfChildrenSizes);
        if (sumOfChildrenSizes <= 5) {
            return 0.0;
        }
        return 0.8;
    })
    .attr("font-size",10)
    .style("text-anchor","middle")
    .append("textPath")
    .attr("xlink:href",function(d,i){return "#s"+i;})
    .attr("startOffset",function(d,i){return "50%";})
    .text(function(d){return d.name.toUpperCase();})

Fortunately, centering text on an arc was just a matter of setting the right property. 幸运的是,在弧上居中文本只是设置正确属性的问题。

Just updating some of VividD's code. 只是更新一些VividD的代码。

The describeArc function was not working correctly for arcs with less than 180 degrees, and the start and end variables was flipped on the function and when calling it. 对于小于180度的弧,describeArc函数无法正常工作,并且在函数和调用时都会触发start和end变量。

Here is an updated describeArc function that handles all alternatives of arcs, including small arcs and upside-down arcs: 这是一个更新的describeArc函数,它处理所有弧的替代方案,包括小弧和倒置弧:

function describeArc(x, y, radius, startAngle, endAngle) {
  var start = polarToCartesian(x, y, radius, startAngle);
  var end = polarToCartesian(x, y, radius, endAngle);
  var arcLength = endAngle - startAngle;
  if (arcLength < 0) arcLength += 360;
  var longArc = arcLength >= 180 ? 1 : 0;
  var d = [
    "M", start.x, start.y,
    "A", radius, radius, 0, longArc, 1, end.x, end.y
  ].join(" ");
  return d;
}

With this change the function should be called with reversed start and end values that make more sense: 通过此更改,应使用反转的开始和结束值调用函数,这更有意义:

describeArc(d.x, d.y, d.r, -160, 160);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM