使用 D3 JS 将饼图的每个圆弧旋转 180(如太阳)。如何计算翻译参数
Rotate every arc of pie chart 180 (like sun) with D3 JS. How to calculate translate parameters
我正在使用 d3 js 制作饼图。我想将饼图的每个弧度旋转 180。我知道我无法完全解释这里显示的是我的 fiddle link.
[fiddle]: https://jsfiddle.net/dsLonquL/
如何获取 translate() 函数的动态参数。
基本上你需要计算出每个圆弧边缘的中心点。我用这个例子来寻求帮助:How to get coordinates of slices along the edge of a pie chart?
这没问题,但我需要旋转点以使它们处于正确的位置。因为它是弧度的,所以旋转如下:
var rotationInRadians = 1.5708 * 1.5;
现在使用我使用数据作为路径之前的示例,所以开始和结束角度以及中心点如下所示:
var thisAngle = (d.startAngle + rotationInRadians + (d.endAngle + rotationInRadians - d.startAngle + rotationInRadians) / 2);
var x = centreOfPie[0] + radius * 2 * Math.cos(thisAngle)
var y = centreOfPie[1] + radius * 2 * Math.sin(thisAngle)
我创建了一个函数来在这些点显示圆圈以澄清:
function drawCircle(points, colour) {
svg.append('circle')
.attr('cx', points[0])
.attr('cy', points[1])
.attr('r', 5)
.attr('fill', colour);
}
像这样在当前函数中调用它:
drawCircle([x, y], color(d.data.label))
然后进行相应的平移和旋转:
return 'translate(' + (x) + ',' + y + ') rotate(180)';
我添加了一个过渡,所以你可以看到它的工作。这是最后的 fiddle :
https://jsfiddle.net/thatOneGuy/dsLonquL/7/
编辑
在您的评论中,您说您希望最大的部分保留在中间。所以我们需要 运行 通过细分并获得最大的。我还处理了重复项,即如果两个或多个段的大小相同。
这是添加的代码:
var biggestSegment = {
angle: 0,
index: []
};
path.each(function(d, i) {
var thisAngle = (d.endAngle - d.startAngle).toFixed(6);//i had to round them as the numbers after around the 7th or 8th decimal point tend to differ tet theyre suppose to be the same value
if (i == 0) {
biggestSegment.angle = thisAngle
} else {
if (biggestSegment.angle < thisAngle) {
biggestSegment.angle = thisAngle;
biggestSegment.index = [i];
} else if (biggestSegment.angle == thisAngle) {
console.log('push')
biggestSegment.index.push(i);
}
}
})
现在遍历每条路径检查它是否大于当前值,如果它覆盖最大值并记下索引。如果相同,则将索引添加到索引数组。
现在在平移路径时,您需要根据上面的索引数组检查当前索引,看它是否需要旋转。像这样:
if (biggestSegment.index.indexOf(i) > -1) {
return 'translate(' + (centreOfPie[0]) + ',' + (centreOfPie[1]) + ')' // rotate(180)';
} else {
return 'translate(' + (x) + ',' + y + ') rotate(180)';
}
已更新 fiddle:https://jsfiddle.net/thatOneGuy/dsLonquL/8/
我编辑了 3 个值以与其余值不同。继续改变这些,看看你的想法:)
这是一个纯中学几何作业。
CASE 1:每个扇形旋转的顶点都在圆的外线上
// ... previous code there
.attr('fill', function(d, i) {
return color(d.data.label);
})
.attr("transform", function(d, i) {
var a = (d.endAngle + d.startAngle) / 2, // angle of vertex
dx = 2 * radius * Math.sin(a), // shift/translate is two times of the vertex coordinate
dy = - 2 * radius * Math.cos(a); // the same
return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
});
CASE 2:顶点在弦的中心
// ... previous code there
.attr('fill', function(d, i) {
return color(d.data.label);
})
.attr("transform", function(d, i) {
var dx = radius * (Math.sin(d.endAngle) + Math.sin(d.startAngle)), // shift/translation as coordinate of vertex
dy = - radius * (Math.cos(d.endAngle) + Math.cos(d.startAngle)); // the same for Y
return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
});
我正在使用 d3 js 制作饼图。我想将饼图的每个弧度旋转 180。我知道我无法完全解释这里显示的是我的 fiddle link.
[fiddle]: https://jsfiddle.net/dsLonquL/
如何获取 translate() 函数的动态参数。
基本上你需要计算出每个圆弧边缘的中心点。我用这个例子来寻求帮助:How to get coordinates of slices along the edge of a pie chart?
这没问题,但我需要旋转点以使它们处于正确的位置。因为它是弧度的,所以旋转如下:
var rotationInRadians = 1.5708 * 1.5;
现在使用我使用数据作为路径之前的示例,所以开始和结束角度以及中心点如下所示:
var thisAngle = (d.startAngle + rotationInRadians + (d.endAngle + rotationInRadians - d.startAngle + rotationInRadians) / 2);
var x = centreOfPie[0] + radius * 2 * Math.cos(thisAngle)
var y = centreOfPie[1] + radius * 2 * Math.sin(thisAngle)
我创建了一个函数来在这些点显示圆圈以澄清:
function drawCircle(points, colour) {
svg.append('circle')
.attr('cx', points[0])
.attr('cy', points[1])
.attr('r', 5)
.attr('fill', colour);
}
像这样在当前函数中调用它:
drawCircle([x, y], color(d.data.label))
然后进行相应的平移和旋转:
return 'translate(' + (x) + ',' + y + ') rotate(180)';
我添加了一个过渡,所以你可以看到它的工作。这是最后的 fiddle :
https://jsfiddle.net/thatOneGuy/dsLonquL/7/
编辑
在您的评论中,您说您希望最大的部分保留在中间。所以我们需要 运行 通过细分并获得最大的。我还处理了重复项,即如果两个或多个段的大小相同。
这是添加的代码:
var biggestSegment = {
angle: 0,
index: []
};
path.each(function(d, i) {
var thisAngle = (d.endAngle - d.startAngle).toFixed(6);//i had to round them as the numbers after around the 7th or 8th decimal point tend to differ tet theyre suppose to be the same value
if (i == 0) {
biggestSegment.angle = thisAngle
} else {
if (biggestSegment.angle < thisAngle) {
biggestSegment.angle = thisAngle;
biggestSegment.index = [i];
} else if (biggestSegment.angle == thisAngle) {
console.log('push')
biggestSegment.index.push(i);
}
}
})
现在遍历每条路径检查它是否大于当前值,如果它覆盖最大值并记下索引。如果相同,则将索引添加到索引数组。
现在在平移路径时,您需要根据上面的索引数组检查当前索引,看它是否需要旋转。像这样:
if (biggestSegment.index.indexOf(i) > -1) {
return 'translate(' + (centreOfPie[0]) + ',' + (centreOfPie[1]) + ')' // rotate(180)';
} else {
return 'translate(' + (x) + ',' + y + ') rotate(180)';
}
已更新 fiddle:https://jsfiddle.net/thatOneGuy/dsLonquL/8/
我编辑了 3 个值以与其余值不同。继续改变这些,看看你的想法:)
这是一个纯中学几何作业。
CASE 1:每个扇形旋转的顶点都在圆的外线上
// ... previous code there
.attr('fill', function(d, i) {
return color(d.data.label);
})
.attr("transform", function(d, i) {
var a = (d.endAngle + d.startAngle) / 2, // angle of vertex
dx = 2 * radius * Math.sin(a), // shift/translate is two times of the vertex coordinate
dy = - 2 * radius * Math.cos(a); // the same
return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
});
CASE 2:顶点在弦的中心
// ... previous code there
.attr('fill', function(d, i) {
return color(d.data.label);
})
.attr("transform", function(d, i) {
var dx = radius * (Math.sin(d.endAngle) + Math.sin(d.startAngle)), // shift/translation as coordinate of vertex
dy = - radius * (Math.cos(d.endAngle) + Math.cos(d.startAngle)); // the same for Y
return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
});