Можно играть по памяти и после этого рисовать на невидимом холсте. И когда вы будете готовы, скопируйте все байты на видимый холст. И я вижу, вы используете много случайного. Это медленная инструкция. Попробуйте создать случайную таблицу и реализовать свою собственную случайную функцию
Вот версия со скоростью 12-15 кадров в секунду, но я думаю, вы можете достичь лучшей производительности, манипулируя пикселями. Итак, этот код основан на вашем решении, но я не могу увеличить fps, потому что слишком много вызовов функций, манипулирования объектами и подобной пахлавы. (код ниже достигает более 100 кадров в секунду)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>sarkiroka</title>
</head>
<body>
<canvas id="plane" width="500" height="500"></canvas>
<script>
// variable and function for speedup
const randomTable = [];
const randomTableLength = 1000007;
const fpsMinimum = 1000 / 30;
for (let i = 0; i < randomTableLength; i++) {
randomTable.push(Math.random() * 500);
}
let randomSeed = 0;
function getNextRandom() {
if (++randomSeed >= randomTableLength) {
randomSeed = 0;
}
return randomTable[randomSeed];
}
// html, dom speedup
const canvas = document.getElementById("plane");
const context = canvas.getContext("2d");
const drawCanvas = document.createElement('canvas');
drawCanvas.setAttribute('width', canvas.getAttribute('width'));
drawCanvas.setAttribute('height', canvas.getAttribute('height'));
const drawContext = drawCanvas.getContext('2d');
drawContext.fillStyle = "#000";
let animatelist = [];
let point = function (x, y, size) {
animatelist.push(this);
this.x = x;
this.y = y;
this.size = size;
this.render = () => {
this.x = getNextRandom();
this.y = getNextRandom();
drawContext.fillRect(this.x, this.y, this.size, this.size);
}
}
for (let i = 0; i < 100000; i++) {
new point(getNextRandom(), getNextRandom(), 0.3);
}
//the animation
let lastBreath = Date.now();
const animateListLength = animatelist.length;
let framesDrawed = 0;
let copied = false;
const maximumCallstackSize = 100;
function continouslyAnimation(deep) {
if (copied) {
drawContext.clearRect(0, 0, 500, 500);
for (let i = 0; i < animateListLength; i++) {
animatelist[i].render();
}
copied = false;
}
framesDrawed++;
let now = Date.now();
if (lastBreath + 15 > now && deep < maximumCallstackSize) {
continouslyAnimation(deep + 1);
} else { // to no hangs browser
lastBreath = now;
setTimeout(continouslyAnimation, 1, 1);
}
}
setInterval(() => {
console.log(framesDrawed);
framesDrawed = 0;
}, 1000);
continouslyAnimation(0);
function copyDrawToVisible() {
context.putImageData(drawContext.getImageData(0, 0, 499, 499), 0, 0);
copied = true;
}
setInterval(copyDrawToVisible, fpsMinimum);
</script>
</body>
</html>
А вот решение для манипулирования пикселями с гораздо большей производительностью (более 100 кадров в секунду, 220–245 кадров в секунду на моем компьютере):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>sarkiroka</title>
</head>
<body>
<canvas id="plane" width="500" height="500"></canvas>
<script>
// variable and function for speedup
const randomTable = [];
const randomTableLength = 1000007;
for (let i = 0; i < randomTableLength; i++) {
randomTable.push(Math.random());
}
let randomSeed = 0;
function getNextRandom() {
if (++randomSeed >= randomTableLength) {
randomSeed = Math.round(Math.random() * 1000);
}
return randomTable[randomSeed];
}
// html, dom speedup
const canvas = document.getElementById("plane");
const context = canvas.getContext("2d");
let framesDrawed = 0;
function drawNoise() {
context.clearRect(0, 0, 500, 500);
let imageData = context.createImageData(499, 499);
let data = imageData.data;
for (let i = 0, length = data.length; i < length; i += 4) {
if (0.1 > getNextRandom()) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 255;
}
}
context.putImageData(imageData, 0, 0);
framesDrawed++;
}
setInterval(drawNoise, 0);
setInterval(() => {
console.log('fps', framesDrawed);
framesDrawed = 0;
}, 1000)
</script>
</body>
</html>
Пояснение: для шума вам не нужна функция / объект для каждого цветного пикселя. Доверьтесь статистике и случайности. В моем примере 10% пикселей окрашены, но мы не знаем, сколько пикселей перед рендерингом. Но это не важно. Издалека это просто так идеально. И самое главное: он может набирать больше кадров в секунду.
Общий совет:
- Какой код повторяется много раз, организуйте из него что сможете
- Рисуйте только на холсте, когда закончите рисовать в памяти
- Измерьте то, что идет медленно, и оптимизируйте его, и только это