我正在编写神经网络的虚拟化,我想在每次训练迭代中重绘它,所以我有带有onclick回调的下一个按钮:
startButton.onclick = () => {
for (let i = 0; i < trainData.length; i++) {
setTimeout(() => {
network.trainSample(trainData[i])
ctx.clearRect(0, 0, width, height)
drawNN(network)
}, 0)
}
}
问题是,如果我起飞setTimeout
,它将执行所有训练,最后重绘所有内容。
据我所知,有一个事件循环和setTimeout
的窍门是什么,它在事件队列中创建了一个Job,该任务将现在不准确地执行,但要尽快执行。
好的,但是如果画布绘制是异步的,并且绘制延期到最后,为什么它的api是同步的?
最小示例:
const canv = document.getElementById('myCanv')
const ctx = canv.getContext('2d')
ctx.strokeStyle = '#000000'
for (let x = 0; x <= 100; x++) {
ctx.clearRect(0, 0, 100, 100)
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(x, 100)
ctx.stroke()
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas width="100" height="100" id="myCanv"></canvas>
</body>
</html>
答案 0 :(得分:1)
您的用法是不正确的,即使画布绘制是同步的,您也很可能只看到最后一帧,并且它们之间有些奇怪的动画。您需要的是代替标准循环,而是使用某种动画循环。例如:
let i = 0;
function animationLoop() {
if (i < trainData.length) {
network.trainSample(trainData[i]);
ctx.clearRect(0, 0, width, height);
drawNN(network);
i++;
requestAnimationFrame(animationLoop);
}
}
requestAnimationFrame(animationLoop);
在这里,我正在使用requestAnimationFrame
,它将导致每秒大约60帧。我对您的情况的猜测可能仍然太快。您可以在setTimeout
函数中使用附加的animateLoop
来限制每秒的帧数。