2013-05-13 6 views
1

У меня есть этот кусок холста анимации, выставляющаяся некоторые странные характеристики:Является ли context.clearRect() действительно ЭТО дорого?

http://jsbin.com/olasol/2/edit

Я на последнюю версию Chrome. Я использую встроенный монитор FPS от Chrome (вы можете активировать его, перейдя на about:flags). я пометил строку в разделе JavaScript, который я думаю, что это потенциальный преступник:

fallingctx.clear(); 

Эта линия не делает ничего особенного. Он вызывает функцию, которая в свою очередь вызывает clearRect().

В "странные" вещи, которые я замечаю, являются:

  1. clear(); функция вызывает очень заметное падение фпс на моем ноутбуке (Core 2 Duo), но не на моем рабочем столе (i5 2500K).

  2. Для снятия этой линии достаточно производить 60 кадров в секунду на моем ноутбуке. Как и ожидалось, холст не очищается после каждого кадра, но все же он создает стабильные 60 кадров в секунду.

  3. Откат FPS происходит только тогда, когда мое окно Chrome находится на большой стороне! Когда я сжимаю окно и перезаряжаю, этого не происходит! (Разве дороже очистить большой прямоугольник?).

  4. Я попытался заменить clear() на drawImage() полного белого JPEG, чтобы покрыть холст. JavaScript способен выполнять 200 drawImage() выполнение каждого цикла для меньших частиц изображения (что видно из второй точки). Однако, когда я добавляю один drawImage для всего холста, он снова отстает! (Убедитесь, что выходной сигнал занимает весь экран, чтобы воспроизвести результат.)

Почему все это происходит? Как это исправить?

+0

Обратите внимание, что вещь 'window.requestAnimationFrame' не обязательно должна быть в функции. Кроме того, не используйте 'new Object()', и использование синтаксиса точек для доступа к свойствам вместо скобок, вероятно, является хорошей идеей. – Ryan

+0

Расширение прототипа такого рода вещей также, вероятно, то, что вы не должны делать. – Ryan

+0

Итак, в высокопроизводительной настройке вы расширяете собственный объект с помощью метода, который обращается к this.canvas ..., который * может вызвать некоторые проблемы. Это лучше? http://jsbin.com/olasol/12/edit – Ryan

ответ

2

Это действительно зависит от оборудования, но подумайте о том, что должен делать вызов clearRect! Что-то по существу должно обнулить часть памяти, достаточную для обработки содержимого холста. Это может быть дорогостоящим. Подумайте о том, сколько памяти должно содержать RGBA при разрешениях HD ... Это более двух миллионов пикселей данных, около 8 МБ в байтах. По общему признанию, не все , что в наши дни, но если есть проблемы с пропускной способностью или кешированием связанные с нажатием памяти на видеокарту или что-то, что вы делаете 60 раз в секунду ... ну, ждите проблем.

То, что я слышал часто, - это просто очистить место, где изображение было ранее нарисовано. См. http://jsbin.com/olasol/6/edit

Я внесла следующие изменения для вас.

for (var i=0; i< noOfDrops; ++i) 
    { 
     fallingctx.clearRect(
      fallingDrops[i].x-1, 
      fallingDrops[i].y-1, 
      fallingDrops[i].image.width+2, 
      fallingDrops[i].image.height+2); 
    } 
    for (var i=0; i< noOfDrops; ++i) 
    { 
     fallingDrops[i].y += fallingDrops[i].speed; //Set the falling speed 
     fallingctx.drawImage (fallingDrops[i].image, fallingDrops[i].x, fallingDrops[i].y); 
    } 

Там, вероятно, хорошая причина, по которой мне нужно clearRectвокруг где было вынесено изображение, но простая причина ускользает от меня. (Это как-то связано с тем, что отображается не совсем в пикселе, указанном ... Я точно забуду).

Вы также должны сделать что-то о том, вы начинаете цикл рендеринга до загрузки изображения (также в jsbin), поэтому я добавил

var imgSource = "http://lorempixel.com/20/20/sports/"; 
var imgObj = new Image(); 

и заменил superinit

function superinit() 
{ 
    imgObj.onload = function(){ 
     flowerfallsetup(); 
     requestAnimFrame(flowerfall); 
    } 
    imgObj.onerror = function(){ 
     alert("could not load image"); 
    } 
    imgObj.src = imgSource; 
} 

Редактировать: Я забыл упомянуть из-за установки предыдущего изображения, я изменил строку в вашем flowerfallsetup:

 fallingDr["image"] = imgObj; 

Существует множество способов обработки асинхронной загрузки изображений, я просто выбрал тот, который был простым для этого примера.

Редактировать: Должен признаться, может быть, немного больше. Он отлично работает на настольных браузерах, но на iPhone там есть проблемы отсечения. Если я смогу понять, что вызывает проблему, я постараюсь опубликовать обновление.

+1

Зачем бить существующее изображение на холст быстрее, чем очищать его? – icktoofay

+0

хорошо, это, похоже, решена моя проблема. Но я нашел это: http://phrogz.net/tmp/image_move_sprites_canvas.html Мой ноутбук быстрее очищает куски холста вместо всего (135 кадров в секунду и 80 кадров в секунду), но мой рабочий стол быстрее очищает весь вещь! (200fps против 170fps). любая идея почему? и спасибо за подробный ответ :) – viswa

+0

проверен на моем Nexus S- Он также быстрее выполняет очистку только изображений (44Fps против 31 кадра в секунду). это запутывает: | – viswa

Смежные вопросы