将弯曲的 textPath 居中放置在圆弧内
Center the curved textPath inside an arc
给定一条沿着给定弧线的弯曲文本路径,所述文本路径如何在弧线内居中?
其中我通过反复试验在上手动设置x和dy,这样结果就是我想要的(文本沿圆弧居中)。
但我正在动态生成许多圆弧,需要一种动态居中文本位置的方法(取决于 d)。
我认为这里的子问题是 d.x 和 d.dx 如何与 dx 和 x 相关? y 也一样。
使用 SVG 路径的 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!");
为了子孙后代;)
之所以需要 dy
是因为 TextPath
从 outerRadius
定义的路径的开头开始绘制文本,使其基线与路径匹配.然后它将继续到这条外部路径的末端并环绕到内部路径。我还没有找到或想出一种方法来计算字体的高度并相应地调整 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>
给定一条沿着给定弧线的弯曲文本路径,所述文本路径如何在弧线内居中?
其中我通过反复试验在
但我正在动态生成许多圆弧,需要一种动态居中文本位置的方法(取决于 d)。
我认为这里的子问题是 d.x 和 d.dx 如何与
使用 SVG 路径的 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!");
为了子孙后代;)
之所以需要 dy
是因为 TextPath
从 outerRadius
定义的路径的开头开始绘制文本,使其基线与路径匹配.然后它将继续到这条外部路径的末端并环绕到内部路径。我还没有找到或想出一种方法来计算字体的高度并相应地调整 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>