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>
如何尝试在现有弧内获得随机坐标?
我目前正在根据用户数据渲染饼图,并希望在随机位置的每条弧上渲染多个点 - 然而,它们可能在弧外
目前,我使用的是与每个圆弧的质心的随机偏差(在一定范围内)。这种方法是有问题的,因为弧可能太小并且点最终在弧之外。
目前我真的无法提供任何示例代码,因为到目前为止我实际上只是在渲染一个包含五个切片的饼图。
我使用 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>