沿着D3圆包装布局中的圆形文字 [英] Text along circles in a D3 circle pack layout

查看:1093
本文介绍了沿着D3圆包装布局中的圆形文字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在圈子包布局中标记某些圈子,其中文本沿着圈子本身流动。



以下是一个实验性





我想在此图形上放置曲线标签,在这些条件下:




  • 圆形代表省份(只有depth == 1)(不列颠哥伦比亚省,阿尔伯塔省等)

  • 所有儿童的总和,省份的议会席位数目大于5个。

  • 省份名称应为大写UPPERCASE。



你可以看到我在代码中的一些尝试。我一直在尝试几个小时。我的主要问题是圆圈中的圆圈现在在XY空间中,而在第一个jsfiddle中,所有圆圈都有坐标系原点的中心。



也许你可以



底层数据基于此表:





(注意:与解决方案:





如注释中所述,关键部分生成弧作为普通的vanilla svg弧,而不是通过d3.svg.arc()。



定义弧的SVG规则很清楚,但有点难以管理。以下是 arcs的svg语法的互动浏览器



此外,这两个函数帮助我在定义正确的弧的过程中:

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

函数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;
}

这是直接生成曲线标签的代码:

  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){sum bb $ b // 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){return50%;})
.text(function(d){return d.name.toUpperCase();})

幸运的是,将文本置于圆弧上只是为了设置正确的属性。


I am trying to label some circles in a circle pack layout with text that flows along the circle itself.

Here is one experimental 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. But let's say we don't care about it.

Here is another 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)
  • The sum of sizes of all children (in other words, number of parliament seats allotted) of the province is greater than 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 X Y space, whereas, in the first jsfiddle, all circles have centers in coordinate system origin.

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 I asked the other day, however this is a related, but independent experiment.)

I decided to use regular SVG arcs instead of d3.svg.arc(). I still think it is a right decision. However, here is what I have now: :) 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.

Here is jsfiddle of the solution:

As mentioned in comments, the key part was generating arcs as plain vanilla svg arcs, not via d3.svg.arc().

SVG rules for defining arcs are clear, but a little hard to manage. Here is an interactive explorer of svg syntax for arcs.

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.

这篇关于沿着D3圆包装布局中的圆形文字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆