在甜甜圈饼图中显示数据标签 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 提供了帮助函数,使其变得非常容易。

在您展示的示例中,您只检查鼠标光标是否位于矩形区域内。但实际上你想检查鼠标光标是否在一个圆圈内。为此,您可以使用 dist(x1,y1,x2,y2) function。确定鼠标光标位于饼图上方后,您将需要确定它位于哪个段上。这可以通过找到从图表中心向右绘制的线(或您开始绘制楔形的方向)与从图表中心到鼠标光标绘制的线之间的角度来完成。这可以使用 p5.VectorangleBetween() 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,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]]}`,centerY);
        pop();
      }
    }

    start += angle;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...