【问题标题】:Text along circles in a D3 circle pack layoutD3 圆形包布局中的圆形文本
【发布时间】:2014-01-21 10:51:02
【问题描述】:

我正在尝试使用沿圆圈本身流动的文本标记circle pack layout 中的一些圆圈。

这是一个实验性的jsfiddle

如您所见,可以沿圆形呈现文本,在其顶部居中。尽管浏览器对弯曲 SVG 文本的渲染很糟糕。但假设我们不关心它。

这是另一个jsfiddle

我想在这个图表上放置弯曲的标签,在这些条件下:

  • 圆圈代表一个省(仅深度==1)(不列颠哥伦比亚省、阿尔伯塔省等)
  • 该省所有儿童的人数之和(即分配的议会席位数)大于 5。
  • 省名应全部大写。

您可以在代码本身中看到我的一些尝试。我已经尝试了几个小时。我的主要问题是圆圈中的圆圈现在位于 X Y 空间中的某个位置,而在第一个 jsfiddle 中,所有圆圈的中心都在坐标系原点。

也许你可以通过重新审视这个来帮助我。

基础数据基于此表:

(注意:这与我前几天问的问题'Circle packs as nodes of a D3 force layout'有些相关,但这是一个独立的实验。)

我决定使用常规的 SVG 弧而不是 d3.svg.arc()。我仍然认为这是一个正确的决定。但是,这就是我现在所拥有的::) jsfiddle

【问题讨论】:

  • 一个快速说明:由于将 cx 和 cy 属性分配给 var arc,因此引发了异常。如果您将这两个注释掉,那么标签会全部显示在左上角(您提到的坐标问题)。这可能是显而易见的,并且您已经通过实验知道了一些事情,但想指出作为一个健全性检查。
  • 是的,这是一种“开发”的例子,所以这是正常的。 :) 我知道所有捆绑在那个角落的文本。这实际上是我的问题——如何把它放在正确的地方。感谢您引起我的注意,现在其他人也会知道发生了什么... :)
  • 关于 attr startOffset = "<length>"docs 说:如果给出的 不是百分比(这是你给它的),那么 'startOffset' 代表在当前用户坐标系中测量的沿路径的距离。按照文档,然后一个登陆distance along a path。目前,这似乎是 textPath 元素与指定 x,y 坐标的可能性之间的唯一联系。希望这不是兔子的踪迹
  • 我认为这里的 d3.svg.arc() 是一个障碍。除了在 (0,0) 中具有中心之外,它不能被定义。在我看来,切换到常规 SVG arc 会起作用。
  • 在你修复它之前,我很快就把你最新的小提琴分叉了!我将它存储起来,以便绘制有关巴西 Cangaço 的任何未来故事的可能性。这是这些人中的famous picture :) 抱歉,有点轻浮……工作太努力了……

标签: javascript svg d3.js label circle-pack


【解决方案1】:

注意(因为我正在回答我的问题):如果你们中的一些人已经在这个问题上花费了时间并找到了另一个解决方案,请发布它,我会接受你的回答。感谢@FernOfTheAndes 参与寻找这个解决方案的过程,因为它充满了使用 svg arcs 的痛苦和痛苦。

这里是jsfiddle的解决方案:

正如 cmets 中所述,关键部分是将弧生成为普通的 svg 弧,而不是通过 d3.svg.arc()。

定义圆弧的 SVG 规则很明确,但有点难以管理。这里是an interactive explorer of svg syntax for 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;       
}

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

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

幸运的是,在圆弧上居中文本只是设置正确属性的问题。

【讨论】:

  • 我会在这里发布。和你的差不多,其他各种摆弄。为了让文本圆内,同时仍然是正确的,我使路径半径比圆半径小一点。我试图使用“textLength”属性来压缩文本以适应,但它似乎不适用于&lt;textpath&gt; 元素。 jsfiddle.net/2hM3s/4
  • @AmeliaBR 我刚把.style("font-size",12)改成.attr("font-size",12),结果是:(jsfiddle.net/VividD/vCG6w)(报错从我的例子中一直在那里)
  • @AmeliaBR 我认为您应该将此作为答案发布,这对未来的读者能够看到两种方法很有好处。
  • @AmeliaBR 我的意思是说,现在可以说 .attr("font-size",8) 可以使文本尽可能小,因为他/她希望:更新(jsfiddle.net/VividD/ vCG6w)
  • 我对@VividD 最新小提琴的贡献很小:moving the labels according to the different user choices。可以通过过渡和其他修饰来改进,但你明白了。
【解决方案2】:

只是更新了一些 VividD 的代码。

对于小于 180 度的圆弧,describeArc 函数无法正常工作,并且在函数和调用它时,开始和结束变量被翻转。

这是一个更新后的 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;
}

通过此更改,应使用更有意义的反向开始和结束值调用函数:

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

【讨论】:

    猜你喜欢
    • 2019-02-11
    • 2014-02-09
    • 1970-01-01
    • 2013-08-06
    • 2013-01-27
    • 1970-01-01
    • 2015-03-19
    • 2011-10-13
    • 2011-08-29
    相关资源
    最近更新 更多