javascript - 如何在 5 秒后停止此画布动画绘制新粒子并在单击时从零粒子重新启动?
问题描述
我想在 5 秒后停止绘制新粒子并在单击任意位置重新开始绘制。
这是动画的代码https://codepen.io/Jeremboo/pen/ENVaMY。
现在它一直在绘制,直到您单击屏幕再次重新启动它。
我想要的是在 5 秒后停止绘图,然后单击任意位置从零粒子重新启动它。我尝试了以下停止但我无法再次启动它。
这是js代码
/**/ const canvas = document.createElement('canvas');
/**/ const context = canvas.getContext('2d');
/**/ let windowWidth = canvas.width = window.innerWidth;
/**/ let windowHeight = canvas.height = window.innerHeight;
/**/ canvas.id = 'canvas';
/**/ document.body.insertBefore(canvas, document.body.firstChild);
/**/ /* ---- CORE END ---- */
/* ---- CREATING ZONE ---- */
/* ---- SETTINGS ---- */
const numberParticlesStart = 1000;
const particleSpeed = 0.3;
const velocity = 0.9;
const circleWidth = 50;
/* ---- INIT ---- */
let particles = [];
const getRandomFloat = (min, max) => (Math.random() * (max - min) + min);
/* ---- Particle ---- */
function Particle (x, y) {
this.x = x;
this.y = y;
this.vel = {
x : getRandomFloat(-20, 20)/100,
y : getRandomFloat(-20, 20)/100,
min : getRandomFloat(2, 10),
max : getRandomFloat(10, 100)/10
}
this.color = 'rgba(255, 255, 255, 0.05)';
}
Particle.prototype.render = function() {
context.beginPath();
context.fillStyle = this.color;
context.arc(this.x, this.y, 1, 0, Math.PI * 2);
context.fill();
};
Particle.prototype.update = function() {
const forceDirection = {
x: getRandomFloat(-1, 1),
y: getRandomFloat(-1, 1),
};
if (Math.abs(this.vel.x + forceDirection.x) < this.vel.max) {
this.vel.x += forceDirection.x;
}
if (Math.abs(this.vel.y + forceDirection.y) < this.vel.max) {
this.vel.y += forceDirection.y;
}
this.x += this.vel.x * particleSpeed;
this.y += this.vel.y * particleSpeed;
if (Math.abs(this.vel.x) > this.vel.min) {
this.vel.x *= velocity;
}
if (Math.abs(this.vel.y) > this.vel.min) {
this.vel.y *= velocity;
}
this.testBorder();
};
Particle.prototype.testBorder = function() {
if (this.x > windowWidth) {
this.setPosition(this.x, 'x');
} else if (this.x < 0) {
this.setPosition(windowWidth, 'x');
}
if (this.y > windowHeight) {
this.setPosition(this.y, 'y');
} else if (this.y < 0) {
this.setPosition(windowHeight, 'y');
}
};
Particle.prototype.setPosition = function(pos, coor) {
if (coor === 'x') {
this.x = pos;
} else if (coor === 'y') {
this.y = pos;
}
};
/* ---- Functions ----*/
function loop() {
let i;
const length = particles.length;
for (i = 0; i < length; i++) {
particles[i].update();
particles[i].render();
}
requestAnimationFrame(loop);
}
/* ---- START ---- */
function init() {
let i;
for (i = 0; i < numberParticlesStart; i++) {
const angle = Math.random() * 360;
particles.push(new Particle(
windowWidth * 0.5 + (Math.cos(angle) * circleWidth),
windowHeight * 0.5 - (Math.sin(angle) * circleWidth),
));
}
}
init();
window.onresize = () => {
windowWidth = canvas.width = window.innerWidth;
windowHeight = canvas.height = window.innerHeight;
particles = [];
context.clearRect(0,0, windowWidth, windowHeight);
init();
}
window.addEventListener('click', () => {
particles = [];
context.clearRect(0,0, windowWidth, windowHeight);
init();
});
loop();
我用 this 替换了函数 loop() 以在 5 秒后停止它 -
function loop(stp) {
let i;
const length = particles.length;
for (i = 0; i < length; i++) {
particles[i].update();
particles[i].render();
}
if (stp > 5000) return;
requestAnimationFrame(loop);
}
解决方案
尽量依靠系统时钟,因为setTimeout
并不setInterval
准确
let start;
function loop(startTime) {
let i;
if(startTime){
// Set the current time in milliseconds from 1st of jenuary 1970
start = new Date().getTime();
}
const length = particles.length;
for (i = 0; i < length; i++) {
particles[i].update();
particles[i].render();
}
// Comparison from current dateTime with the stored one
// as setInterval and setTimeout are not accurate
if (start - (new Date().getTime() >= 5000) return;
requestAnimationFrame(loop);
}
loop(true);
推荐阅读
- python-3.x - 如何解决 VS Code 中的“无法从源代码解析导入“django.contrib”?
- java - 带有过滤器和映射的可选内部Java铸造
- javascript - 在服务器流式传输中取消客户端的 grpc 调用
- r - 为什么ggplot2堆积条形图中缺少一些数据?
- javascript - nodemailer和outlook365的身份验证问题
- node.js - 字段的NodeJS multer文件名
- python - 跳过文本文件中的特定行进行处理,但在输出中也返回这些行
- html - 如何在单元格的左边框上添加按钮
- c# - 当 T 或 Object 传递一个集合时循环它
- android - 将 JetPack compose 组件转换为 ImageBitmap