【问题标题】:How to right/end align text along an textPath inside an arc using d3.js?如何使用 d3.js 沿弧内的 textPath 右/结束对齐文本?
【发布时间】:2014-03-06 22:05:22
【问题描述】:

这是小提琴:http://jsfiddle.net/DevChefOwen/CZ6Dp/

var text = g.append("text")
            .style("font-size",30)
            .style("fill","#000")
            .attr("dy",0)
            .append("textPath")
            .attr("xlink:href","#yyy")
            .style("text-anchor","left") // using "end", the entire text disappears
            .text("some text");

我尝试了许多不同的方法都无济于事。左对齐是最容易的部分。但是,如果你做了中间处理,你只会看到“text”而不是“some text”,这意味着“some”只是被隐藏了,因为它对于给定的弧线“超出了范围”。

但是,如果我添加了:

        .attr("startOffset","39%")

(如这里:http://jsfiddle.net/DevChefOwen/2H99c/

它看起来是正确对齐的,但在以编程方式尝试获取文本元素的宽度/高度并寻找宽度/高度的急剧变化(这似乎是错误的并且可能容易出错)之外,我似乎无法找到一种方法来右对齐文本。

我也尝试过使用 SVG 路径(基本上是弯曲的弧线),当“text-anchor”设置为“left”时,文本也会发生相同的消失行为。

感谢您的宝贵时间!

【问题讨论】:

    标签: svg d3.js


    【解决方案1】:

    这个问题有点令人困惑。问题是没有对齐路径末尾的文本——这很容易用"text-anchor"="end""startOffset"="100%" 完成。

    但是,将这些设置与 d3 arc 函数创建的路径一起使用,您最终会看到文本围绕内部曲线的末端和左侧直边拐弯,到达 arc 函数定义的路径末端: http://jsfiddle.net/CZ6Dp/8/

    真正的问题是,您希望文本对齐的路径(形状的外圆弧)只是定义形状的路径的一部分。

    (顺便说一下,“left”和“right”不是“text-anchor”属性的有效值,将被忽略)。

    @defghi1977 的回答提供了一种解决问题的方法,即确定您想要使用的路径段的长度并相应地调整起始偏移量。

    解决该问题的另一种方法是创建一个单独的路径(未在屏幕上绘制),该路径仅代表您希望用于定位文本的路径部分。

    有多种方法可以创建仅代表外部弧线的路径 (some example code here)。 @defghi1977 使用正则表达式从现有路径中获取它的方法可能对您的情况最有效。但实际上,我不仅要创建一个临时元素来计算长度,还必须将新路径添加到 DOM,以便它可以用作<textPath> 元素的参考路径。 (我认为这是这种方法的缺点——DOM 元素数量的两倍!)

    var path = g.append("svg:path")
        .attr("d", arct)
        .style("fill","#ccc")
        .attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")")
        .each(function(d,i) {
            var justArc = /(^.+?)L/; 
            //grab everything up to the first Line statement
            var thisSelected = d3.select(this);
            var arcD = justArc.exec( thisSelected.attr("d") )[1];
            defs.append("path")
                .attr("id", "yyy") //normally the id would be based on the data or index  
                .attr("d", arcD)
                .attr("transform", thisSelected.attr("transform") );
                //if you can avoid using transforms directly on the path element, 
                //you'll save yourself having to repeat them for the text paths...
        });
    
    var text = g.append("text")
                .style("font-size",30)
                .style("fill","#000")
                .attr("dy",0)
                .append("textPath")
                .attr("xlink:href","#yyy")
                .style("text-anchor","end") 
                .attr("startOffset","100%")
                .text("some text");
    

    http://jsfiddle.net/CZ6Dp/9/

    同样,考虑到额外的 DOM 加载,@defghi1977 的方法可能稍微好一点,尽管这个版本的好处是不依赖于浏览器对 getTotalLength 的支持。但据我所知,该方法实现得相当好。

    因此,为了完整起见,请考虑这是一种替代方法。

    【讨论】:

    • 感谢您提供更深入的解释和替代方法。我同意@defghi1977 的方法稍微可取:鉴于您的方法与他/她的方法相通并且更全面,因此您的方法是选定的答案。
    【解决方案2】:

    此路径由 4(或 5)个路径段构成。
    所以,这个问题将被解决以获得第一弧路径长度。
    但我不知道如何使用 d3.js 获取子路径长度,因此我直接使用 svgdom。
    我试图修复你的代码。如果这段代码不是你所希望的,对不起。

    1. 要结束的路径锚属性。
    2. 定义函数以获取 startOffset 值。

    var path = g.append("svg:path")
        .attr("id","yyy")
        .attr("d", arct)
        .style("fill","#ccc")
        .attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")");
    
    var text = g.append("text")
            .style("font-size",30)
            .style("fill","#000")
            .attr("dy",0)
            .append("textPath")
            .attr("xlink:href","#yyy")
            //.style("text-anchor","left") // using "end", the entire text disappears
            .attr("text-anchor", "end")
            .text("some text")
            .attr("startOffset",function(){
                var d = document.getElementById("yyy").getAttribute("d");
                var tmp = document.createElementNS("http://www.w3.org/2000/svg" ,"path");
                //get the arc segment of path
                var arc = d.match(/(^.+?)L/)[1];
                tmp.setAttribute("d", arc);
                //return offset position
                return tmp.getTotalLength();
            });
    

    【讨论】:

    【解决方案3】:

    我认为混淆来自text-anchor 的含义 - 这不是“相对于我将证明父母的哪个位置”,而是“我应该将我的哪一部分与开始对齐”。

    尝试使用startOffset 移动原点是对的。由于路径的外半径比内半径长,因此正确的起始偏移量略大于路径的一半(大约 53%)。

    只需稍微调整一下您的设置,您就应该拥有它。 Here's a fiddle 我对您正在寻找的内容的解释。

    【讨论】:

    • 我明白你的意思,但不幸的是,因为我会以不同的弧角对齐不同长度的文本,所以玩弄不会很有效。如果您有兴趣,@defghi1977 有一个解决方案,它可以从数学上推断出需要设置的位置,因此不同的文本长度仍然会产生正确的对齐方式。仍然感谢您的积分。
    猜你喜欢
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多