D3 JS倒置路径文本

PCo*_*lho 6 svg d3.js

在这种情况下,是否可以显示文字不是颠倒的?

http://jsfiddle.net/paulocoelho/Hzsm8/1/

码:

var cfg = {
    w:400,
    h:400
};

var g = d3.select("#testdiv").append("svg").attr("width", cfg.w).attr("height", cfg.h).append("g")

var arct = d3.svg.arc()
        .innerRadius(cfg.h / 5)
        .outerRadius(cfg.h / 3)
        .startAngle(Math.PI/2)
        .endAngle(Math.PI*1.5);

var path = g.append("svg:path")
    .attr("id","yyy")
    .attr("d", arct)
    .style("fill","blue")
    .attr("transform", "translate("+cfg.w/2+","+cfg.h/6+")");

var text = g.append("text")
            .style("font-size",30)
            .style("fill","#F8F8F8")
            .attr("dy",35)
            .append("textPath")
            .attr("xlink:href","#yyy")
            .attr("startOffset",50)
            .text("some text")
    ;
Run Code Online (Sandbox Code Playgroud)

小智 8

一个很好的例子是Nadieh Bremer 用D3.js在Arcs上放置文本.一个冗长的博客,有许多图像,以下是一个摘录:

在底部翻转文本

你可能已经觉得它完成了那个样子.但我发现这些标签沿着下半部分是颠倒的,而且难以阅读.如果那些标签被翻转,我更喜欢它,所以我可以再次从左到右阅读它们.

为此,我们需要沿着下半部分切换当前弧形路径的起点和终点坐标,以便从左到右绘制它们.此外,必须将sweep-flag设置为0以获得从左到右以逆时针方式运行的弧

因此,对于最终的行为,让我们在.each()语句中添加几行代码

//Create the new invisible arcs and flip the direction for those labels on the bottom half
.each(function(d,i) {
    //Search pattern for everything between the start and the first capital L
    var firstArcSection = /(^.+?)L/;    

    //Grab everything up to the first Line statement
    var newArc = firstArcSection.exec( d3.select(this).attr("d") )[1];
    //Replace all the commas so that IE can handle it
    newArc = newArc.replace(/,/g , " ");

    //If the end angle lies beyond a quarter of a circle (90 degrees or pi/2) 
    //flip the end and start position
    if (d.endAngle > 90 * Math.PI/180) {
        var startLoc    = /M(.*?)A/,        //Everything between the capital M and first capital A
            middleLoc   = /A(.*?)0 0 1/,    //Everything between the capital A and 0 0 1
            endLoc      = /0 0 1 (.*?)$/;   //Everything between the 0 0 1 and the end of the string (denoted by $)
        //Flip the direction of the arc by switching the start and end point (and sweep flag)
        var newStart = endLoc.exec( newArc )[1];
        var newEnd = startLoc.exec( newArc )[1];
        var middleSec = middleLoc.exec( newArc )[1];

        //Build up the new arc notation, set the sweep-flag to 0
        newArc = "M" + newStart + "A" + middleSec + "0 0 0 " + newEnd;
    }//if

    //Create a new invisible arc that the text can flow along
    svg.append("path")
        .attr("class", "hiddenDonutArcs")
        .attr("id", "donutArc"+i)
        .attr("d", newArc)
        .style("fill", "none");
});
Run Code Online (Sandbox Code Playgroud)

自上一节以来唯一改变的是添加了if语句.要翻转开始和结束位置,我们可以使用更多的正则表达式.当前的起始x和y位置由大写字母M和大写字母A之间的所有内容给出.当前半径由大写字母A和x轴旋转的0 0 1之间的所有内容表示,大弧标记和扫旗.最后,结尾位置由0 0 1和字符串结尾之间的全部给出(由正则表达式中的$表示).

因此,我们将所有部分保存在不同的变量中,并使用切换了开始和结束位置的if语句中的最后一行来构建/替换newArc.

textPath部分需要一个小的改动.对于下半部分圆弧,dy属性不应将标记提升到圆弧路径上方,而应降低圆弧路径下方的标签.所以我们需要一个小的if语句,它会产生两个不同的dy值.(为了能够在if语句中使用d.endAngle,我在.data()步骤中用饼干(donutData)替换了donutData.您仍然可以使用d.data而不是d来引用数据本身可以在.text()代码行中看到.)

//Append the label names on the outside
svg.selectAll(".donutText")
    .data(pie(donutData))
   .enter().append("text")
    .attr("class", "donutText")
    //Move the labels below the arcs for those slices with an end angle greater than 90 degrees
    .attr("dy", function(d,i) { return (d.endAngle > 90 * Math.PI/180 ? 18 : -11); })
   .append("textPath")
    .attr("startOffset","50%")
    .style("text-anchor","middle")
    .attr("xlink:href",function(d,i){return "#donutArc"+i;})
    .text(function(d){return d.data.name;});
Run Code Online (Sandbox Code Playgroud)


Pau*_*eau 1

看起来,当 d3 创建这些填充弧之一时,它实际上创建了一个填充路径形状,该形状始终(?)从右侧开始并顺时针前进 - 即使您反转 startAngle 和 endAngle 也是如此。

如果您手动创建自己的圆弧路径,并将文本放在上面,您就可以让它做正确的事情。

var cfg = {
    w:400,
    h:400
};

var g = d3.select("#testdiv").append("svg").attr("width", cfg.w).attr("height", cfg.h).append("g")

var arct = d3.svg.arc()
        .innerRadius(cfg.h / 5)
        .outerRadius(cfg.h / 3)
        .startAngle(Math.PI/2)
        .endAngle(Math.PI*1.5);

var path = g.append("svg:path")
    .attr("id","yyy")
    .attr("d", arct)
    .style("fill","blue")
    .attr("transform", "translate("+cfg.w/2+","+cfg.h/6+")");

// Radius of line text sits on. A value of 3.5 makes it slightly closer to the
// outer radius (so text is placed in the middle of the blue line).
var textpathRadius = (cfg.h / 3.5);

// Make a path for the text to sit on that goes in an anti-clockwise direction.
var textpath = g.append("svg:path")
    .attr("id","zzz")
    .style("display","none")
    .attr("d", "M -"+textpathRadius+" 0 A "+textpathRadius+" "+textpathRadius+" 0 0 0 "+textpathRadius+" 0")
    .attr("transform", "translate("+cfg.w/2+","+cfg.h/6+")");

var text = g.append("text")
            .style("font-size",30)
            .style("fill","#F8F8F8")
            .attr("dy",0)
            .append("textPath")
            .attr("xlink:href","#zzz")
            .attr("startOffset","50%")
            .style("text-anchor","middle")
            .text("some text");
Run Code Online (Sandbox Code Playgroud)

我以前从未使用过 d3,因此可能有一种更简单或更干净的方法来完成我所做的事情。但至少它应该为您提供一个起点。

更新的小提琴: http: //jsfiddle.net/3DfVD/