gpt4 book ai didi

javascript - 为什么这个脚本在 Javascript 中会出现延迟?

转载 作者:行者123 更新时间:2023-12-03 07:23:10 25 4
gpt4 key购买 nike

我制作了一个脚本,其中应该有实时吸引彼此的小球。问题是速度非常慢。我使用了动画帧,所以我认为它应该更新每一帧,但事实并非如此。这是代码:

$(function() {

var mouseDown
var c = document.getElementById('myCanvas');
var ctx = c.getContext("2d");
var objects = []

c.addEventListener("mousedown", onMouseDown);
c.addEventListener("mouseup", onMouseUp);

function createSquare(x, y, size, direction, xVel, yVel) {
this.x = x;
this.y = y;
this.size = size;
this.drawStylus = drawStylus;
};

function drawStylus() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
};

function getDistance(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

function draw() {
ctx.clearRect(0, 0, 5000, 5000);
for (i = 0; i < objects.length; i++) {

var x = objects[i][0]
var y = objects[i][1]
var size = objects[i][2]
var dir = Math.random() * Math.PI * 2
var force = 0
var xVel = 0
var yVel = 0
for (n = 0; n < objects.length; n++) {
if (n != i) {
force = 100 * objects[n][2] / getDistance(x, y, objects[n][0], objects[n][1])
angle = Math.atan2(y - objects[n][1], x - objects[n][0])
xVel += force * -Math.cos(angle)
yVel += force * -Math.sin(angle)
window.requestAnimationFrame(draw)
};
};

ctx.beginPath();
ctx.arc(x + xVel, y + yVel, size, 0, 2 * Math.PI);
ctx.fill();
};
};

function onMouseDown() {
mouseDown = true
x = event.clientX
y = event.clientY
size = 100

animation = function() {
size = size + 20

var cursorSquare = new createSquare(x, y, size);
cursorSquare.drawStylus();
anim = window.requestAnimationFrame(animation)
};
window.requestAnimationFrame(animation)
};

function onMouseUp() {
if (mouseDown) {
window.cancelAnimationFrame(anim)
var newSquare = new createSquare(x, y, size);
objects.push([x, y, size])
mouseDown = false
};
};

function loop() {
draw();
window.requestAnimationFrame(loop);
};

function init() {
loop();
};

init()

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<canvas id='myCanvas' width="5000" height="5000" style="border:1px solid #000000;"></canvas>

最佳答案

您正在为每个对象调用 requestAnimationFrame,这是使用 requestAnimationFrame (RAF) 的错误方法。

每帧只能调用一次,而不是每个对象调用一次。

function mainLoop(time){ // main loop RAF will add the time in milliseconds to the arguments.
ctx.clearRect(0,0,canvas.width,canvas.height); // clear
draw(); // call the draw loop
requestAnimationFrame(loop); // request next frame
}
requestAnimationFrame(loop); // request next frame

使用绘图函数,如 ctx.arc非常慢。如果改为渲染图像,您将获得更好的性能ctx.drawImage 。您可以创建一个 Canvas ,在该 Canvas 上绘制圆弧,然后使用 ctx.drawImage(canvasImage,... 绘制该 Canvas 。以获得更快的更新。

另一个答案建议您使用 forEach ,不要使用 forEach或任何涉及回调的数组函数,因为它们比使用标准循环(for、while、do)慢得多

更新

随着浏览器世界中事物的快速变化,我已经测试了 forEach 在这种情况下的使用,但在这种情况下,消息并不好。 forEachfor 相比,每次迭代仍然会增加显着的额外开销, while ,和do while

需要注意的重要一点(以及为什么我删除了最后一段)是每次迭代的开销,如果迭代次数很少并且每次迭代的代码量很大,那么开销是微不足道的,不值得麻烦的是,个人编码风格应该选择在这些情况下使用什么风格。

如果另一方面,您有大量迭代并且每次迭代处理量很小,那么使用 forEach 将显着影响循环的性能。

这对于 Chrome、Edge 和 Firefox 来说都是如此,所有这些都显示带有内联代码(不调用函数)的标准迭代(for 循环)是最快的,其次是带有 a 的标准迭代,比标准迭代慢 10%函数调用(如 forEach),然后是 forEach,每次迭代的额外开销超过 2 倍。 (每个测试都使用 15-20 比 1 的代码平衡,即迭代内的代码比迭代所需的最小代码长 15-20 倍。所以一行用于 forforEach 循环和 10-循环内有 15 行代码。)

如果您正在处理数千到数万的数组,则不值得担心差异,如果您正在处理数千到数百万的数组,则应该避免 forEach .

注意:我没有测试forEach在类型化数组上,因为这在这种情况下不适用。

测试于

  • Chrome 版本 50.0.2661.37 beta-m
  • 火狐46.0b2
  • 边缘25.10586

关于javascript - 为什么这个脚本在 Javascript 中会出现延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36115240/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com