javascript - Javascript 中的丢球,不是一个一个丢,而是所有的球一次丢。(必须与“迭代器”相关)
问题描述
我尝试使用 D3 进行钟形曲线可视化。具体来说,我想一一展示每一个球的下落动作。
我在 Observable 中看到了一个例子。因为我正在学习 D3,所以我尝试在我的 javascript 代码中运行一些东西。原始 Observable 代码如下:
https ://observablehq.com/@cbuie/pachinko-simulator
我在javascript中转换了代码,如下所示。
var random = d3.randomNormal() // Try randomUniform?
const n = 2000
const width = window.innerWidth;
const height = 400
const radius = 2
const dodge = dodger(radius * 2 + 1);
const margin = ({
top: 0,
right: 10,
bottom: 20,
left: 10
});
const values = Float64Array.from({
length: n
}, random);
const x = d3.scaleLinear(d3.extent(values), [margin.left, width - margin.right]);
const svg = d3.select('body').append('svg').attr('width', width).attr('height', height).style('overflow', 'visible')
// var fillScale = d3.scaleSequentialLog(chroma.interpolateSinebow)
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
function dodger(radius) {
const radius2 = radius ** 2;
const bisect = d3.bisector(d => d.x);
const circles = [];
return function(x) {
const l = bisect.left(circles, x - radius);
const r = bisect.right(circles, x + radius);
let y = 0;
for (let i = l; i < r; ++i) {
const {
x: xi,
y: yi
} = circles[i];
const x2 = (xi - x) ** 2;
const y2 = (yi - y) ** 2;
if (radius2 > x2 + y2) {
y = yi + Math.sqrt(radius2 - x2) + 1e-6;
i = l - 1;
continue;
}
}
circles.splice(bisect.left(circles, x, l, r), 0, {
x,
y
}); //what is this?
return y;
};
}
for (let i = 0; i < n; ++i) {
if (i % 5 === 0)
svg.node();
const cx = x(values[i]); // x(values[i]);->what is this?
const cy = height - margin.bottom - dodge(cx) - radius - 1;
svg.append("circle")
.attr("cx", cx)
.attr("cy", -400)
.attr("r", radius)
.attr('fill', 'red')
// .attr("fill","#9e0dd7") //purple
.transition()
.duration(650)
.ease(d3.easeBounce)
.attr("cy", cy);
}
svg.node();
<script src="https://d3js.org/d3.v5.min.js"></script>
最终结果是一样的,但我的代码没有显示球的运动,而只是像“baam!”一样立即显示了球的最终分布。我很确定它与“生成器”或“迭代器”等有关。
谁能让我知道如何解决它,以便我可以像“沙漏”一样将球从顶部到底部一一移动?
解决方案
我相信这就是您要寻找的东西,是的,它与生成器功能有关,加上有一个间隔计时器来获取下一个生成器值。
function* gen() {
var random = d3.randomNormal(); // Try randomUniform?
const n = 2000;
const width = window.innerWidth;
const height = 400;
const radius = 2;
const dodge = dodger(radius * 2 + 1);
const margin = { top: 0, right: 10, bottom: 20, left: 10 };
const values = Float64Array.from({ length: n }, random);
const x = d3.scaleLinear(d3.extent(values), [
margin.left,
width - margin.right
]);
const svg = d3
.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("overflow", "visible");
// var fillScale = d3.scaleSequentialLog(chroma.interpolateSinebow)
svg
.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
function dodger(radius) {
const radius2 = radius ** 2;
const bisect = d3.bisector(d => d.x);
const circles = [];
return function(x) {
const l = bisect.left(circles, x - radius);
const r = bisect.right(circles, x + radius);
let y = 0;
for (let i = l; i < r; ++i) {
const { x: xi, y: yi } = circles[i];
const x2 = (xi - x) ** 2;
const y2 = (yi - y) ** 2;
if (radius2 > x2 + y2) {
y = yi + Math.sqrt(radius2 - x2) + 1e-6;
i = l - 1;
continue;
}
}
circles.splice(bisect.left(circles, x, l, r), 0, { x, y }); //what is this?
return y;
};
}
for (let i = 0; i < n; ++i) {
if (i % 5 === 0) yield svg.node();
const cx = x(values[i]); // x(values[i]);->what is this?
const cy = height - margin.bottom - dodge(cx) - radius - 1;
svg
.append("circle")
.attr("cx", cx)
.attr("cy", -400)
.attr("r", radius)
.attr("fill", "red")
.attr("fill", "#9e0dd7") //purple
.transition()
.duration(650)
.ease(d3.easeBounce)
.attr("cy", cy);
}
yield svg.node();
}
const genratorAnimation = gen();
let result = genratorAnimation.next();
//genratorAnimation.next();
let interval = setInterval(function(){
if(!result.done) {
genratorAnimation.next();
}
else {
clearInterval(interval)
}
}, 50);
<script src="https://d3js.org/d3.v5.min.js"></script>
推荐阅读
- r - 如何检查数据框中的列中是否有某些字符用于 if 语句?
- java - 尝试创建形状时在 JavaFX 上收到错误
- javascript - Mongoose setOnInsert :在查询中使用计算属性
- c++ - 使用 QListWidget 的 Qt 命令日志
- c# - 创建元素数组 c# 控制台
- cluster-computing - 解决 SLURM “sbatch:错误:批处理作业提交失败:请求的节点配置不可用”错误
- sql - Symfony 4 - SQLSTATE[42000] 未知原因更改表
- java - localhost api 请求的 Http 失败响应:0 未知错误 - Angular
- archive - 借助 elementor 在作者档案中显示自定义帖子类型
- generics - 与可区分联合上的另一个接口的成员实现接口