我试图弄清楚如何提高使用 requestAnimationFrame 重新绘制画布的粒子文本效果的性能 (fps)。它在较新的设备上运行良好,但是当我在较慢的 CPU 上测试它时,帧数下降到无法忍受的水平。我尝试减少屏幕上的粒子数量,但没有任何效果。即使我从回调函数中删除更新和绘制方法,并为 requestAnimationFrame 设置超时,我也只能获得 2-3 fps 的改进。我附上了一个链接,指向下面来自 Frank's Laboratory 的示例,以展示我正在使用的内容。非常感谢任何帮助。
https://codepen.io/franksLaboratory/pen/VwKEeqR
const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext("2d");
canvas.width = 1200;
canvas.height = 600;
let particleArray = [];
let adjustX = -10;
let adjustY = 3;
// get mouse mouse position //
let mouse = {
x: null,
y: null,
radius: 150
}
let canvasPosition = canvas.getBoundingClientRect();
window.addEventListener('mousemove',
function(e){
mouse.x = e.x - canvasPosition.left;
mouse.y = e.y - canvasPosition.top;
});
ctx.font = 'bold 16px Verdana';
ctx.fillText('LIQUID', 5, 30);
const data = ctx.getImageData(0, 0, canvas.width, 100);
class Particle {
constructor(x, y){
this.x = x + 200,
this.y = y - 100,
this.size = 8,
this.baseX = this.x,
this.baseY = this.y,
this.density = ((Math.random() * 30) + 1);
}
draw() {
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
update() {
// check mouse position/particle position - collision detection
let dx = mouse.x - this.x;
let dy = mouse.y - this.y;
let distance = Math.sqrt(dx*dx + dy*dy);
let forceDirectionX = dx / distance;
let forceDirectionY = dy / distance;
// distance past which the force is zero
var maxDistance = mouse.radius;
// convert (0...maxDistance) range into a (1...0).
// Close is near 1, far is near 0
// for example:
// 250 => 0.75
// 100 => 0.9
// 10 => 0.99
var force = (maxDistance - distance) / maxDistance;
// if we went below zero, set it to zero.
if (force < 0) force = 0;
let directionX = (forceDirectionX * force * this.density)
let directionY = (forceDirectionY * force * this.density);
if (distance < mouse.radius + this.size){
this.x -= directionX;
this.y -= directionY;
} else {
if (this.x !== this.baseX ) {
let dx = this.x - this.baseX;
this.x -= dx/10;
} if (this.y !== this.baseY) {
let dy = this.y - this.baseY;
this.y -= dy/10;
}
}
}
}
function init(){
particleArray = [];
for (var y = 0, y2 = data.height; y < y2; y++) {
for (var x = 0, x2 = data.width; x < x2; x++) {
if (data.data[(y * 4 * data.width) + (x * 4) + 3] > 128) {
let positionX = x + adjustX;
let positionY = y + adjustY;
//let positionX = x;
//let positionY = y;
particleArray.push(new Particle(positionX * 15, positionY * 15));
}
}
}
}
function animate(){
//ctx.fillStyle = 'rgba(0,0,0,0.5)';
//ctx.fillRect(0,0,innerWidth,innerHeight);
ctx.clearRect(0,0,innerWidth,innerHeight);
for (let i = 0; i < particleArray.length; i++){
particleArray[i].update();
particleArray[i].draw();
}
connect();
requestAnimationFrame(animate);
}
init();
animate();
/*
// RESIZE SETTING - empty and refill particle array every time window changes size + change canvas size
window.addEventListener('resize',
function() {
canvas.width = innerWidth;
canvas.height = innerHeight;
init();
});*/
function connect(){
let opacityValue = 1;
for (let a = 0; a < particleArray.length; a++) {
for (let b = a; b < particleArray.length; b++) {
let distance = (( particleArray[a].x - particleArray[b].x) * (particleArray[a].x - particleArray[b].x))
+ ((particleArray[a].y - particleArray[b].y) * (particleArray[a].y - particleArray[b].y));
if (distance < 3600) {
opacityValue = 1 - (distance/3600);
let dx = mouse.x - particleArray[a].x;
let dy = mouse.y - particleArray[a].y;
let mouseDistance = Math.sqrt(dx*dx+dy*dy);
if (mouseDistance < mouse.radius / 2) {
particleArray[a].size = 25;
ctx.strokeStyle='rgba(255,255,150,' + opacityValue + ')';
} else if (mouseDistance < mouse.radius - 50) {
particleArray[a].size = 20;
ctx.strokeStyle='rgba(255,255,180,' + opacityValue + ')';
} else if (mouseDistance < mouse.radius + 20) {
particleArray[a].size = 15;
ctx.strokeStyle='rgba(255,255,210,' + opacityValue + ')';
} else {
particleArray[a].size = 8;
ctx.strokeStyle='rgba(255,255,255,' + opacityValue + ')';
}
ctx.lineWidth = 20;
ctx.beginPath();
ctx.moveTo(particleArray[a].x, particleArray[a].y);
ctx.lineTo(particleArray[b].x, particleArray[b].y);
ctx.stroke();
}
}
}
}
window.addEventListener('resize', function(){
canvasPosition = canvas.getBoundingClientRect();
});