2016-06-05 3 views
1

Я пытаюсь добиться перемещения картины внутри холста, но через несколько секунд (или минут) ситуация становится неуправляемой.Оптимизировать движущийся узор на холсте?

canvas = document.querySelector('canvas'); 
canvas.width = 400; 
canvas.height = 240; 
ctx = canvas.getContext('2d'); 
image = new Image(); 
image.src = 'pattern.png'; 
t = 0; 

update(); 

function update() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.save(); 

    ctx.translate(t, 2*t); 
    ctx.fillStyle = ctx.createPattern(image, 'repeat'); 
    ctx.rect(0, 0, canvas.width, canvas.height); 
    ctx.fill(); 
    ctx.restore(); 

    t++; 

    requestAnimationFrame(update); 
} 

Вот jsfiddle (предупреждение потребление памяти).

Моя цель - использовать этот холст в качестве текстуры для спрайта THREEjs, непрерывно работающего в сцене. Я не могу анимировать материал спрайтов, играющий с uvOffsets, так как будет 3 или 4 прозрачных шаблона, движущихся в разных направлениях и перекрывающих друг друга. Возможно ли его настроить?

Благодарим вас заблаговременно.

+0

Каков ваш конкретный вопрос? «tweak» может означать что угодно. Кроме того, не лучше ли писать собственный шейдер, а не отправлять холст в материал? – 2pha

+0

Мой вопрос - знать, есть ли лучший способ достичь этого результата. Благодаря этому методу использование процессора становится очень высоким. Через несколько минут (100% -ный процессор в Safari, на последнем MacBook Pro). – xAlien95

+1

Возможный дубликат [Холст HTML5 замедляется с каждым штрихом и очисткой] (http://stackoverflow.com/questions/9558895/html5-canvas-slows-down-with-each-stroke-and-clear) – GameAlchemist

ответ

1

Причина, по которой она замедляется с течением времени, заключается в том, что rect() будет добавлять и накапливать на объект пути с течением времени, поэтому каждый раз, когда вызывается fill(), все эти пробелы прямоугольника заполняются.

Просто замените эту строку:

ctx.rect(0, 0, canvas.width, canvas.height); 

с

ctx.fillRect(0, 0, canvas.width, canvas.height); 

Необязательно добавить beginPath() перед добавлением rect(). fillRect() растеризуется напрямую, не добавляя прямоугольник к пути.

Также не забудьте компенсировать положение прямоугольника, так как область, которую он заполняет, также перемещается, в конце концов, вне области холста. Просто компенсировать с помощью обратного значений перевода:

ctx.fillRect(-t, -t*2, canvas.width, canvas.height); 

В новых браузерах мы можем использовать setTransform непосредственно на CanvasPattern объекта:

// assuming pattern is set as fill-style 
ctx.fillStyle.setTransform(1,0,0,1, x, y); 

модифицированный пример вкл. некоторые другие предложения по оптимизации цикла:

... 
image.onload = function() { 
    ctx.fillStyle = ctx.createPattern(image, 'repeat'); 
    update(); 
}; 

function update() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 

    ctx.setTransform(1,0,0,1, t, 2*t); // optionally replace save/restore/translate 
    ctx.fillRect(-t, -t*2, canvas.width, canvas.height); 

    t++; 

    requestAnimationFrame(update); 
} 
+0

Благодарим вас за ответ. Таким образом, шаблон [перемещается вниз] (https://jsfiddle.net/qdmc9fat/), не воссоздавая повторяющийся контент слева и сверху. Я также пробовал использовать 'beginPath()', но результат тот же. Возможно ли иметь такое же поведение моего jsfiddle? – xAlien95

+1

@ xAlien95 вы имеете в виду как [это] (https://jsfiddle.net/epistemex/qdmc9fat/1/)? Поскольку холст переводится, область для fillRect перемещается. Просто компенсируйте, выровняв равную величину в противоположном направлении. – K3N

+1

Я только что придумал то же самое, спасибо! – xAlien95

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