html5 canvas - сохранение путей или областей обрезки для повторного использования - PullRequest
9 голосов
/ 20 сентября 2011

В настоящее время я реализую эффект двумерной деформируемой местности в игре, над которой я работаю, и все идет хорошо, но я могу себе представить, что она очень быстро превратится в скачок производительности, когда я начну добавлять больше слоев к эффекту.

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

Какой-то очень простой код, демонстрирующий то, что я сейчас делаю

for (var i = 0; i < aMousePoints.length; i++)
{
    cRenderContext.save();
    cRenderContext.beginPath();
    var cMousePoint = aMousePoints[i];
    cRenderContext.arc(cMousePoint.x, cMousePoint.y, 30, 0, 2 * Math.PI, false);
    cRenderContext.clip();
    cRenderContext.drawImage(cImg, 0, 0);
    cRenderContext.closePath();
    cRenderContext.restore();
}

По сути, я стремлюсь к эффективному способу рисования моей обтравочной маски для моего изображения снова и снова в каждом кадре

Ответы [ 3 ]

13 голосов
/ 20 сентября 2011

Обратите внимание, что ваш регион отсечения остается точно таким же, за исключением его местоположения x / y.Это большой плюс.

Область отсечения - это одна из вещей, которая сохраняется и восстанавливается с помощью context.save() и context.restore(), поэтому ее можно сохранить таким образом (другими словами, определяя ее только один раз.).Если вы хотите разместить его, вы будете использовать ctx.translate() вместо x, y.

, но, вероятно, более эффективно сделать это вторым способом:

  1. Иметьхолст в памяти (никогда не добавляемый в DOM или не показанный на странице), который предназначен исключительно для содержания области отсечения и имеет размер области отсечения
  2. Применить область отсечения к этому холсту в памяти, изатем нарисуйте изображение на этом холсте.
  3. Затем используйте drawImage с холстом в памяти в контексте вашей игры.Другими словами: cRenderContext.drawImage(in-memory-canvas, x, y);, где x и y - подходящее местоположение.

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

В качестве отдельного соображения производительности не вызывайте save и restore если не нужно.Они требуют времени, и они не нужны в вашем цикле выше.

Если ваш код с открытым исходным кодом, дайте мне знать, и я посмотрю на него в целом с точки зрения производительности, если хотите.

11 голосов
/ 20 сентября 2011

Почему бы не иметь один холст для переднего плана и один холст для фона?Как и в следующей демонстрации

Демонстрация переднего плана / фона (Возможно, я сделал немного за борт, делая демонстрацию: «Я люблю возиться с JS / canvas.

Но в основном холст переднего плана прозрачен помимо содержимого, поэтому он действует как маска поверх фона холста.

5 голосов
/ 07 марта 2015

Похоже, что теперь это возможно с новым path2D объектом.

Новый API Path2D (доступен в Firefox 31+) позволяет хранить пути, что упрощает код рисования на холсте и ускоряет его работу. Конструктор предоставляет три способа создания объекта Path2D:

new Path2D();     // empty path object
new Path2D(path); // copy from another path
new Path2D(d);    // path from from SVG path data

Третья версия, которая использует данные SVG-пути для создания, особенно удобна. Теперь вы можете повторно использовать пути SVG, чтобы рисовать те же фигуры непосредственно на холсте:

var p = new Path2D("M10 10 h 80 v 80 h -80 Z");

Информация взята с официального сайта Mozilla .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...