Мой сценарий заключается в том, что ширина/высота холста динамически изменяются, и я не хочу сбрасывать холст. Вместо этого я использую clearRect(), так как знаю границы, в которых прямоугольник должен быть очищен.

  1. Есть ли способ отключить сброс холста, когда ширина/высота снова установлены?

  2. Есть ли способ сохранить предыдущее состояние и просто загрузить его обратно на холст, не перерисовывая его?

1
Fahad 24 Мар 2011 в 07:11
Вы не можете предотвратить сброс холста при изменении его размера. Вам придется сохранить его, изменить размер, а затем восстановить то, что вы сохранили.
 – 
Gabe
24 Мар 2011 в 07:19
Я думаю, что это немного странно, во всяком случае, я нашел способ, используя GetImageData/PutImageData для сохранения/восстановления, это помогает на данный момент. Что я искал, так это то, что холст не перерисовывается, если пользователь не укажет это, что было бы больше контроля над тем, как холст реагирует на изменения пользователя.
 – 
Fahad
24 Мар 2011 в 08:16

1 ответ

  1. Боюсь, отключить это невозможно, это встроено в спецификацию холста.

    Раздел 4.8.11:

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

  2. Да, и GetImageData/PutImageData — это один из способов, но он, вероятно, намного медленнее, чем следующий:

    Допустим, ваш холст называется realCanvas. Создайте второй холст (мы назовем его fakeCanvas), такого же размера, как и ваш настоящий холст, но сделайте его только в коде javascript и никогда не добавляйте его в документ (чтобы никто никогда не видеть это).

    Затем, прямо перед изменением размера realCanvas, выполните следующую операцию:

    fakeCanvasContext.drawImage(realCanvas, 0, 0);
    

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

    Как только вы закончите с изменением размера, вы можете отрисовать содержимое fakeCanvas обратно на свой реальныйCanvas.

    realCanvasContext.drawImage(fakeCanvas, 0, 0);
    

    Вот и все!

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

    realCanvasContext.drawImage(fakeCanvas,
        0, 0, realCanvas.width, realCanvas.height,
        0, 0, realCanvas.width, realCanvas.height);`
    

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

5
Eric 19 Дек 2013 в 21:44
Я опробовал ваше предложение. Мой сценарий совсем другой, и речь не идет об изменении размера холста. Это своего рода сценарий торговой сетки, в котором обновления на холсте происходят каждые 250 мс, и я получаю нормальную производительность около 8–20% использования ЦП с вашим подходом, это было почти так же, как Get/Put imagedata. Но в любом случае подход drawImage должен помочь мне в других сценариях. Спецификация довольно странная, должен быть метод reset(), который должен сбрасывать холст, изменяя ширину/высоту, холст должен просто увеличивать/уменьшать пиксели, а не перезапускать себя.
 – 
Fahad
26 Мар 2011 в 10:12