在甜甜圈饼图 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.Vectordist(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 上面清晰的解释和代码。