在甜甜圈饼图 p5js 中显示数据标签
Show data labels inside donut pie chart p5js
我正在构建一个 p5js 圆环图,但我很难在中间显示数据标签。我想我已经设法为它设置了正确的边界,但是如何匹配我所处的角度呢?或者有没有一种方法可以通过颜色来匹配?
https://i.stack.imgur.com/enTBo.png
我首先尝试将图表的边界与指针相匹配,我设法使用 mouseX 和 mouseY 做到了这一点。请问有什么建议吗?
if(mouseX >= width / 2 - width * 0.2 && mouseY >= height / 2 - width * 0.2
&& mouseX <= width / 2 + width * 0.2 && mouseY <= height / 2 + width * 0.2)
{
//console.log("YAY!!! I'm inside the pie chart!!!");
}
else
{
textSize(14);
text('Hover over to see the labels', width / 2, height / 2);
}
};
[1]: https://i.stack.imgur.com/enTBo.png
虽然理论上您可以使用 get()
function 检查鼠标光标下像素的颜色并将其与数据集中的一个条目相关联,但我认为您最好进行数学运算确定鼠标当前位于哪个段上。并且 p5.js 提供的辅助函数非常方便。
在您展示的示例中,您只是在检查鼠标光标是否位于矩形区域中。但实际上你想检查鼠标光标是否在一个圆圈内。为此,您可以使用 p5.Vector
的 dist(x1, y1, x2, y2)
function. Once you've established that the mouse cursor is over your pie chart, you'll want to determine which segment it is over. This can be done by finding the angle between a line draw from the center of the chart to the right (or whichever direction is where you started drawing the wedges), and a line drawn from the center of the chart to the mouse cursor. This can be accomplished using the angleBetween()
function。
这是一个工作示例:
const colors = ['red', 'green', 'blue'];
const thickness = 40;
let segments = {
foo: 34,
bar: 55,
baz: 89
};
let radius = 80, centerX, centerY;
function setup() {
createCanvas(windowWidth, windowHeight);
noFill();
strokeWeight(thickness);
strokeCap(SQUARE);
ellipseMode(RADIUS);
textAlign(CENTER, CENTER);
textSize(20);
centerX = width / 2;
centerY = height / 2;
}
function draw() {
background(200);
let keys = Object.keys(segments);
let total = keys.map(k => segments[k]).reduce((v, s) => v + s, 0);
let start = 0;
// Check the mouse distance and angle
let mouseDist = dist(centerX, centerY, mouseX, mouseY);
// Find the angle between a vector pointing to the right, and the vector
// pointing from the center of the window to the current mouse position.
let mouseAngle =
createVector(1, 0).angleBetween(
createVector(mouseX - centerX, mouseY - centerY)
);
// Counter clockwise angles will be negative 0 to PI, switch them to be from
// PI to TWO_PI
if (mouseAngle < 0) {
mouseAngle += TWO_PI;
}
for (let i = 0; i < keys.length; i++) {
stroke(colors[i]);
let angle = segments[keys[i]] / total * TWO_PI;
arc(centerX, centerY, radius, radius, start, start + angle);
// Check mouse pos
if (mouseDist > radius - thickness / 2 &&
mouseDist < radius + thickness / 2) {
if (mouseAngle > start && mouseAngle < start + angle) {
// If the mouse is the correct distance from the center to be hovering over
// our "donut" and the angle to the mouse cursor is in the range for the
// current slice, display the slice information
push();
noStroke();
fill(colors[i]);
text(`${keys[i]}: ${segments[keys[i]]}`, centerX, centerY);
pop();
}
}
start += angle;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
我想我知道问题的根源是@thenewbie 遇到的问题:它是正在使用的 p5 库。我正在使用 p5.min.js 并遇到同样的问题。一旦我开始使用完整的 p5.js 库,问题就解决了,@Paul 的脚本就可以运行了。
这是我在研究这个问题时遇到的 link,这让我找到了解决方案:
https://github.com/processing/p5.js/issues/3973
感谢 Paul 上面清晰的解释和代码。
我正在构建一个 p5js 圆环图,但我很难在中间显示数据标签。我想我已经设法为它设置了正确的边界,但是如何匹配我所处的角度呢?或者有没有一种方法可以通过颜色来匹配?
https://i.stack.imgur.com/enTBo.png
我首先尝试将图表的边界与指针相匹配,我设法使用 mouseX 和 mouseY 做到了这一点。请问有什么建议吗?
if(mouseX >= width / 2 - width * 0.2 && mouseY >= height / 2 - width * 0.2
&& mouseX <= width / 2 + width * 0.2 && mouseY <= height / 2 + width * 0.2)
{
//console.log("YAY!!! I'm inside the pie chart!!!");
}
else
{
textSize(14);
text('Hover over to see the labels', width / 2, height / 2);
}
};
[1]: https://i.stack.imgur.com/enTBo.png
虽然理论上您可以使用 get()
function 检查鼠标光标下像素的颜色并将其与数据集中的一个条目相关联,但我认为您最好进行数学运算确定鼠标当前位于哪个段上。并且 p5.js 提供的辅助函数非常方便。
在您展示的示例中,您只是在检查鼠标光标是否位于矩形区域中。但实际上你想检查鼠标光标是否在一个圆圈内。为此,您可以使用 p5.Vector
的 dist(x1, y1, x2, y2)
function. Once you've established that the mouse cursor is over your pie chart, you'll want to determine which segment it is over. This can be done by finding the angle between a line draw from the center of the chart to the right (or whichever direction is where you started drawing the wedges), and a line drawn from the center of the chart to the mouse cursor. This can be accomplished using the angleBetween()
function。
这是一个工作示例:
const colors = ['red', 'green', 'blue'];
const thickness = 40;
let segments = {
foo: 34,
bar: 55,
baz: 89
};
let radius = 80, centerX, centerY;
function setup() {
createCanvas(windowWidth, windowHeight);
noFill();
strokeWeight(thickness);
strokeCap(SQUARE);
ellipseMode(RADIUS);
textAlign(CENTER, CENTER);
textSize(20);
centerX = width / 2;
centerY = height / 2;
}
function draw() {
background(200);
let keys = Object.keys(segments);
let total = keys.map(k => segments[k]).reduce((v, s) => v + s, 0);
let start = 0;
// Check the mouse distance and angle
let mouseDist = dist(centerX, centerY, mouseX, mouseY);
// Find the angle between a vector pointing to the right, and the vector
// pointing from the center of the window to the current mouse position.
let mouseAngle =
createVector(1, 0).angleBetween(
createVector(mouseX - centerX, mouseY - centerY)
);
// Counter clockwise angles will be negative 0 to PI, switch them to be from
// PI to TWO_PI
if (mouseAngle < 0) {
mouseAngle += TWO_PI;
}
for (let i = 0; i < keys.length; i++) {
stroke(colors[i]);
let angle = segments[keys[i]] / total * TWO_PI;
arc(centerX, centerY, radius, radius, start, start + angle);
// Check mouse pos
if (mouseDist > radius - thickness / 2 &&
mouseDist < radius + thickness / 2) {
if (mouseAngle > start && mouseAngle < start + angle) {
// If the mouse is the correct distance from the center to be hovering over
// our "donut" and the angle to the mouse cursor is in the range for the
// current slice, display the slice information
push();
noStroke();
fill(colors[i]);
text(`${keys[i]}: ${segments[keys[i]]}`, centerX, centerY);
pop();
}
}
start += angle;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
我想我知道问题的根源是@thenewbie 遇到的问题:它是正在使用的 p5 库。我正在使用 p5.min.js 并遇到同样的问题。一旦我开始使用完整的 p5.js 库,问题就解决了,@Paul 的脚本就可以运行了。 这是我在研究这个问题时遇到的 link,这让我找到了解决方案: https://github.com/processing/p5.js/issues/3973
感谢 Paul 上面清晰的解释和代码。