D3.js - 获取弧内的随机点

D3.js - Get a random point within an arc

如何尝试在现有弧内获得随机坐标?

我目前正在根据用户数据渲染饼图,并希望在随机位置的每条弧上渲染多个点 - 然而,它们可能在弧外

目前,我使用的是与每个圆弧的质心的随机偏差(在一定范围内)。这种方法是有问题的,因为弧可能太小并且点最终在弧之外。

目前我真的无法提供任何示例代码,因为到目前为止我实际上只是在渲染一个包含五个切片的饼图。

我使用 this example 作为起点。我所做的是为每个圆弧生成 10 乘以 2 的数字:距中心的距离和角度(以弧度表示)。然后我使用这些值绘制了圆圈。

为了证明它有效,我将半径设置为常量,所以您会看到一圈黑点。如果你愿意,你也可以使用注释掉的行来随机化。

注意圆圈与圆弧的颜色如何相同。

我也不得不减去Math.PI / 2,因为度数和弧度之间的零点不同:

  • 0度是一条垂直线到顶部;
  • 0弧度向右为水平线。 -Math.PI / 2 弧度是一条垂直线到顶部。

const data = [{
    "region": "North",
    "count": "53245"
  },
  {
    "region": "South",
    "count": "28479"
  },
  {
    "region": "East",
    "count": "19697"
  },
  {
    "region": "West",
    "count": "24037"
  },
  {
    "region": "Central",
    "count": "40245"
  }
];

const width = 360;
const height = 360;
const radius = Math.min(width, height) / 2;

const svg = d3.select("#chart-area")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", `translate(${width / 2}, ${height / 2})`);

const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb",
  "#e78ac3", "#a6d854", "#ffd92f"
]);

const pie = d3.pie()
  .value(d => d.count)
  .sort(null);

const arc = d3.arc()
  .innerRadius(0)
  .outerRadius(radius);

// Join new data
const path = svg.selectAll("path")
  .data(pie(data));

// Enter new arcs
path.enter().append("path")
  .attr("fill", (d, i) => color(i))
  .attr("d", arc)
  .attr("stroke", "white")
  .attr("stroke-width", "6px")
  .each(drawPoints);

function drawPoints(d, i) {
  // Generate random numbers (x, y) where x between startAngle
  // and endAngle
  // and y between 0 and radius
  const points = new Array(10).fill(undefined).map(() => ({
    angle: d.startAngle + Math.random() * (d.endAngle - d.startAngle) - Math.PI / 2,
    //radius: Math.random() * radius,
    radius: radius / 2,
  }));

  svg.selectAll(`.point-${i}`)
    .data(points)
    .enter()
    .append('circle')
    .attr('class', `point point-${i}`)
    .attr("fill", (d) => color(i))
    .attr('stroke', 'black')
    .attr('stroke-width', '2px')
    .attr('cx', (d) => d.radius * Math.cos(d.angle))
    .attr('cy', (d) => d.radius * Math.sin(d.angle))
    .attr('r', 3)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js"></script>
<div id="chart-area"></div>