将弧形textPath置于弧内

时间:2015-02-13 12:25:43

标签: d3.js

如果在给定弧之后有一个弯曲的文本路径,那么textpah如何在弧内居中

enter image description here

请参阅this example

在其中,我在< text>上手动设置了x和dy。通过试验和错误,以便结果是我想要的(文本沿弧线居中)。

但我动态生成许多弧,需要一种动态居中文本位置的方法(取决于d)。

我认为这里的子问题是d.x和d.dx与< text>的关系。 dx和x?同样适用于y。

2 个答案:

答案 0 :(得分:1)

为子孙后代;)

您需要dy的原因是因为TextPathouterRadius定义的路径的开头开始,并绘制文本以使其基线与路径匹配。然后它将继续到这个外部路径的末端并环绕到内部路径。我还没有找到或想出一种计算字体高度的方法,并相应地调整dy。或者,您可以创建一个新弧来指导文本并将半径调整为合适的值。

要自动将文本置于上弧上,您需要设置两个属性。第一个是startOffset,以抵消起点;它应该设置为25%,因为线的全长包括内半径和外半径。由于外弧比内弧长,因此可能略微偏离。或者,您可以创建第二条路径,其内半径和外半径相同,并使用该路径作为文本。然后,您需要使用text-anchor并将其设置为middle

如果要防止文本从外部圆弧到内部圆弧缠绕,可以先从路径中删除内部圆弧,然后将文本偏移50%而不是25%。



function removeInnerArc(path) {
  return path.replace(/(M.*A.*)(A.*Z)/, function(_, m1) {
    return m1 || path;
  });
}

var arc = d3.svg.arc()
  .innerRadius(180)
  .outerRadius(220)
  .startAngle(-Math.PI / 4)
  .endAngle(function(t) {
    return t * 2 * Math.PI / 3;
  });

// Generate a new arc to guide the text
// The radius determines the baseline for the text
var textArc = d3.svg.arc()
  .innerRadius(190)
  .outerRadius(190)
  .startAngle(-Math.PI / 4)
  .endAngle(function(t) {
    return t * 2 * Math.PI / 3;
  });

var svg = d3.select("body").append("svg")
  .attr("width", 960)
  .attr("height", 500)
  .append("g")
  .attr("transform", "translate(250,250)");

svg.append("defs").append("path")
  .attr("id", "text-path")
  .attr("d", removeInnerArc(textArc(1)));

svg.append("path")
  .attr("id", "path")
  .attr("d", arc(1));

svg.append("clipPath")
  .attr("id", "text-clip")
  .append("use")
  .attr("xlink:href", "#path");

svg.append("text")
  .attr("clip-path", "url(#text-clip)")
  .append("textPath")
  .attr("xlink:href", "#text-path")
  .text("Hello, curved textPath!")
  // You need the following two lines to position the text correctly
  .attr("text-anchor", "middle")
  .attr("startOffset", "50%");

path {
  fill: #3182bd;
}

text {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 24px;
}

<html>

<head>
  <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:400,600">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

  <script src="http://d3js.org/d3.v3.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>

<body>
</body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

使用SVG Path的getPointAtLength方法。希望这会有所帮助。

var path = svg.append("path")
   .attr("id", "path")
   .attr("d", arc(1));

var text = "Hello, curved textPath!"; 
var pt = path.node().getPointAtLength(path.node().getTotalLength()/2-text.length);

svg.append("text")       
    .attr("clip-path", "url(#text-clip)")    
    .attr("x", pt.x) 
    .attr("dy", 28)
    .append("textPath")
    .attr("xlink:href", "#text-path")
    .text("Hello, curved textPath!");