#javascript #jquery #canvas
#javascript #jquery #холст
Вопрос:
итак, я создал простую систему частиц с canvas и javascript (немного jQuery), но, похоже, я не могу заставить ее работать со скоростью более 8 кадров в секунду на моем старом компьютере, это код:
var starList = [];
function Star(){
this.x = getRandomInt(0, canvas.width);
this.y = getRandomInt(0, canvas.height);
this.vx = getRandomInt(2,5);
this.size = this.vx/5;
this.opacity = getRandomInt(0, 5000) / 10000;
this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
this.draw = function(){
ctx.fillStyle = "rgba(" this.color "," this.opacity ")";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
this.move = function(){
this.x = this.x - this.vx;
if(this.x < 0) {
this.x = canvas.width;
this.opacity = getRandomInt(0, 5000) / 10000;
this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
this.y = getRandomInt(0, canvas.height);
this.size = this.vx/5;
this.vx = getRandomInt(2,5);
}
}
}
var canvas, ctx;
function setCanvas(){
canvas = $('canvas')[0];
ctx = canvas.getContext("2d");
canvas.width = $(window).width()/5;
canvas.height = $(window).height()/5;
}
setCanvas();
function generateStars(){
for(var i = 0; i < 5000; i ){
var star = new Star();
starList.push(star);
}
for(var i = 0; i < starList.length; i ) {
star = starList[i];
star.draw();
}
}
generateStars();
function loop() {
window.requestAnimationFrame(loop);
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//draw and move stars
for(var i = 0; i < starList.length; i ) {
star = starList[i];
star.draw();
star.move();
}
}
Я предполагаю, что использование объектов для частиц (звезд) и перебор массива объектов с индексом 5000, и выполнение этих двух функций сложно для процессора / графического процессора, но как я могу оптимизировать этот код?
Я видел, что другие избегают использования функций в конструкторе, перемещают и рисуют частицы, когда они перебирают массив. Это ускорит работу?
РЕДАКТИРОВАТЬ: игнорируйте getRandomInt и подобные функции, это простые функции, которые я использую для генерации случайного материала.
Комментарии:
1. Помимо того, что это неполный список, и идеи не могут быть проверены, а просто переданы вам, очевидным моментом для поиска, по-видимому, является функция рисования. Кажется, что для рисования 5000 дуг потребуется некоторое время. Вместо этого я бы попробовал нарисовать 5000 прямоугольников. Если это намного быстрее, возможно, все же стоит нарисовать круглый прозрачный png с композицией, чтобы раскрасить его. Вычисление контура дуги будет медленным, и я бы предположил, что аппаратное ускорение не ускоряется. С другой стороны, может быть смешивание / масштабирование / раскраска изображений. Вот кое-что для синхронизации: developer.mozilla.org/en-US/docs/Web/API/Performance/now
Ответ №1:
Самая медленная часть вашего кода — это команды рисования пути:
ctx.fillStyle = "rgba(" this.color "," this.opacity ")";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
Canvas рисуется очень быстро, но 5000 рисунков займут некоторое время.
Вместо этого…
Создайте таблицу спрайтов, содержащую все вариации звезд, которые вы хотите отобразить.
Копирование пикселей из таблицы спрайтов в холст отображения выполняется намного быстрее, чем выполнение команд рисования. Это особенно верно для рисования дуг, где по окружности должно быть вычислено много точек.
Важно!
Ограничьте вариации звезд — зрители не заметят, что ваши звезды не являются бесконечно случайными.
Затем используйте обрезную версию drawimage
, чтобы быстро нарисовать каждый желаемый звездный спрайт из таблицы спрайтов:
// set the global alpha
ctx.globalAlpha = getRandomInt(0, 5000) / 10000;
// cut the desired star-sprite from the spritesheet
// and draw it on the visible canvas
ctx.drawImage( spritesheet, // take from the spritesheet
this.sheetX, this.sheetY, this.width, this.height, // at this sprite's x,y
this.x, this.y, this.width, this.height) // and draw sprite to canvas
Таблица спрайтов
Вы можете использовать второй холст в памяти в качестве таблицы спрайтов и создавать свои звездные спрайты на стороне клиента при первом запуске вашего приложения. drawImage
Команда примет ваш второй холст в памяти в качестве источника изображения (!).
var spritesheet=document.createElement('canvas');
var spriteContext=spriteSheet.getContext('2d');
...
// draw every variation of your stars on the spritesheet canvas
...