Ale*_*gur 3 javascript svg transform d3.js
我有一个小 D3 脚本:
<script>
d3.csv("../data/school_attendance.csv", function(data) {
// Use d3.pie() to create and configure the data that we need in a format that we can enter into.
let arc_data = d3.pie().value(d => d['YTD Enrollment(Avg)']).padAngle(d => 0.0115)(data);
// Create the arc factory function that will render each data segment.
let arc = d3.arc().innerRadius(75).outerRadius(160);
// Run through each element of arc_data, creating and appening the arc for each one.
d3.select("svg")
.append("g")
.attr("id", "transform")
.attr("transform", "translate(400, 200)")
.selectAll('path')
.data(arc_data)
.enter()
.append('path')
.attr('d', arc)
.attr('fill', 'steelblue');
// Use arc and arc_data to calculate centroids, and from there to calculate.
arc_data.forEach(function(d, i) {
[x, y] = arc.centroid(d);
let label = d.data['District']
// let rotation = d['startAngle'] * 180 / Math.PI;
let rotation = d['startAngle'] / Math.PI / 2
d3.select("#transform").append("text")
.attr("x", x).attr("y", y)
.attr("text-anchor", "middle").attr("alignment-baseline", "middle")
.attr("transform", "rotate(" + rotation + ")")
.text(label);
})
})
</script>
Run Code Online (Sandbox Code Playgroud)
这会产生以下输出:
我想旋转文本标签,使它们出现在每个弧段的中间。
然而,在我看来,显而易见的答案是:
let rotation = d['startAngle'] / Math.PI / 2 * 360 - 90;
Run Code Online (Sandbox Code Playgroud)
没有按预期工作:
我的错误是什么,我应该怎么做才能解决它?
这在我看来,这里的问题,一个是设置x和y标签的位置使用attr。相反,翻译它们:
.attr("transform", "translate(" + [x,y] + ")");
Run Code Online (Sandbox Code Playgroud)
在那之后,是数学:
var rotation = (d.startAngle/2 + d.endAngle/2) * 180/Math.PI;
Run Code Online (Sandbox Code Playgroud)
但是上面的变量存在定位从甜甜圈中心到边框的所有文本的问题,并且一些标签(在甜甜圈的左侧)最终颠倒了,从右到左。当我们从左到右阅读时,在我看来,这个三元更优雅:
var rotation = d.endAngle < Math.PI ?
(d.startAngle/2 + d.endAngle/2) * 180/Math.PI :
(d.startAngle/2 + d.endAngle/2 + Math.PI) * 180/Math.PI ;
Run Code Online (Sandbox Code Playgroud)
这是一个演示:
.attr("transform", "translate(" + [x,y] + ")");
Run Code Online (Sandbox Code Playgroud)
var rotation = (d.startAngle/2 + d.endAngle/2) * 180/Math.PI;
Run Code Online (Sandbox Code Playgroud)