【问题标题】:D3.js - Get a random point within an arcD3.js - 获取弧内的随机点
【发布时间】:2021-01-22 08:03:11
【问题描述】:

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

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

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

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

【问题讨论】:

  • 请提供您当前代码的minimal reproducible example。这将帮助我们回答您的问题。另见How to Ask。另外,您使用的是什么版本的 d3? v3 和最新的 v6 之间存在巨大差异
  • 我正在使用 d3.js 6.2.0 我将尝试提出一个简单的示例。

标签: javascript svg d3.js charts pie-chart


【解决方案1】:

我以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>

【讨论】:

  • 这实际上正是我想要的,我可以使用它。谢谢!很抱歉没有提供合适的例子。
  • 别担心,提问和编程一样的技巧
猜你喜欢
  • 2016-09-17
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 2021-08-06
  • 2011-12-24
  • 1970-01-01
相关资源
最近更新 更多