Очистить холст Rect (но сохранить фон) - PullRequest
13 голосов
/ 08 апреля 2011

Я пытаюсь анимировать круг и просто перемещаю его по горизонтали, что отлично работает. Однако, пока круг движется, я должен сделать clearRect над этим кругом, чтобы он перерисовывал себя в горизонтальном направлении. Когда я делаю clearRect, он также заставляет фон иметь белую рамку так эффективно, что он будет одной белой горизонтальной линией в направлении движения круга.

  1. Есть ли способ очистить круг без clearRect?
  2. Если мне придется продолжать перерисовывать фон после clearRect, холст будет мерцать, когда в этой области говорят 10 кругов.

Есть ли другие способы решения этой проблемы?

    function drawcircle() {
        clear();    

        context.beginPath();
        context.arc(X, Y, R, 0, 2*Math.PI, false);                  
        context.moveTo(X,Y);            
        context.lineWidth = 0.3;
        context.strokeStyle = "#999999"; 
        context.stroke();

        if (X > 200)
        {
            clearTimeout(t); //stop
        }
        else
        {
            //move in x dir
            X += dX;
            t = setTimeout(drawcircle, 50);
        }
    }

    function clear() {
        context.clearRect(X-R, Y-R, 2*R, 2*R);
    }

Ответы [ 3 ]

25 голосов
/ 09 апреля 2011

Основы: HTML5 Canvas как графический интерфейс с не сохраняемым режимом рисования

Сначала давайте обсудим, как работает HTML5 Canvas. Как настоящий холст с быстросохнущими масляными красками, когда вы stroke() или fill() или drawImage() на холсте, краска становится частью холста. Хотя вы нарисовали «круг» и видите его таким, пиксели круга полностью заменили фон (или в случае сглаживания по краям круга смешались и навсегда изменили их). Что бы сказал Моне, если бы вы попросили его «переместить» одного из людей на картине немного вправо? Вы не можете перемещать круг, вы не можете стереть круг, вы не можете обнаружить наведение мыши на круг ... потому что нет круга , есть только один 2D массив пикселей.

Некоторые опции

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

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

    Например, см. Этот тест: http://phrogz.net/tmp/image_move_sprites_canvas.html
    В Safari v5.0.4 я вижу 59.4fps, если я очищаю и перерисовываю весь холст один раз за кадр, и 56.8fps, если я использую 20 clearRect() вызовов и 20 drawImage() вызовов, чтобы перерисовать только загрязненную часть фон каждого кадра. В этом случае медленнее , чтобы быть умным и отслеживать маленькие грязные области.

  3. В качестве другой альтернативы используйте графическую систему с сохранением рисунка, такую ​​как SVG или HTML. При этом каждый элемент поддерживается независимо. Вы можете изменить положение предмета, и он будет волшебным образом двигаться; браузер должен сделать обновление наиболее эффективным способом.

    Вы можете сделать это, сохранив мощь пользовательского рисования на холсте, создав и наложив несколько слоев на одну и ту же страницу HTML (используя абсолютное позиционирование CSS и z-index). Как видно из этого теста производительности , перемещение 20 спрайтов через CSS значительно быстрее, чем попытка сделать все это самостоятельно на одном холсте.

Мерцание

Вы писали:

Если мне придется продолжать перерисовывать фон после clearRect, холст будет мерцать, когда в этой области говорят 10 кругов.

Это никогда не было моим опытом. Можете ли вы привести небольшой пример, показывающий эту проблему «мерцания», которая, по вашему мнению, возникнет (пожалуйста, укажите ОС, браузер и версию, с которой вы сталкиваетесь)? Вот два комментария известных разработчиков браузеров , отмечающих, что ни Firefox, ни Safari никогда не должны показывать мерцание.

1 голос
/ 17 июля 2011

Это на самом деле очень легко сделать, просто разместив несколько холстов друг над другом.Вы можете нарисовать свой фон на холсте, который (ждите этого ...) на заднем плане, и нарисовать круги на втором холсте, который находится на переднем плане.(то есть укладывается перед фоновым холстом)

Несколько холстов - это на самом деле один из лучших способов повысить производительность любой анимации, когда элементы конечного изображения перемещаются независимо и не обязательно перемещаются в каждом кадре.Это позволяет избежать перерисовки элементов, которые не перемещались в каждом кадре.Однако следует иметь в виду, что для изменения относительной глубины (например, z-index) предметов, нарисованных на разных холстах, теперь необходимо переупорядочить фактические <canvas> элементы в dom.На практике это редко является проблемой для 2D-игр и анимаций.

0 голосов
/ 08 апреля 2011

Есть два способа сделать это, которые могут уменьшить мерцание, особенно если у вас много кругов.

Один из них - двойная буферизация, и для краткого вопроса по этому вопросу вы можете посмотреть: Поддерживает ли HTML5 / Canvas двойную буферизацию?

По сути, вы рисуете на двух холстах и ​​меняете их местами по мере необходимости.

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

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

ОБНОВЛЕНИЕ:

Исходя из комментария, вы можете посмотреть это обсуждение о двойной буферизации на холсте:

Проблемы с двойной частотой буферизации в холсте HTML

основной идеа, чтобы отслеживать все, что вы нарисовали, с текущей позицией, затем на отдельном холсте, вы перерисовываете все, затем переворачиваете их, а затем я просто перерисовываю снова, на новых позициях, чтобы гарантировать, что изображениевыглядит так, как должно.Поменять их местами - это быстрая операция, единственной проблемой будет, если вы поместите обработчики событий на холст, в этом случае они будут размещены на элементе div или span, окружающем холст, чтобы эта информация не терялась.

...