Является ли CSS Scaling более эффективным, чем drawImage Scaling? - PullRequest
0 голосов
/ 23 сентября 2019

Я хотел бы знать, в чем разница между масштабированием с помощью drawImage и CSS.Я пробовал оба, и CSS, кажется, дает немного более плавные результаты, в то время как drawImage имеет тенденцию быть немного искаженным - особенно если я панорамирую изображение, блекая из разных источников x и y в течение нескольких кадров анимации.Я сделал этот вывод после тестирования на многих различных масштабных факторах.У меня есть простой пример ниже.

var img = new Image();
var ctx = document.querySelector("canvas").getContext("2d");

img.src = "img1000x1000.png";// width and height are 1000

ctx.canvas.width  = 100;
ctx.canvas.height = 100;
ctx.imageSmoothingEnabled = false;

Это выполняется после полной загрузки img.

// method 1 uses drawImage to scale
ctx.drawImage(img, 0, 0, 100, 100, 0, 0, 200, 200);

// method 2 draws the img with no scaling and then uses css to scale
ctx.drawImage(img, 0, 0, 100, 100, 0, 0, 100, 100);
ctx.canvas.style.width  = 200;
ctx.canvas.style.height = 200;

Имейте в виду, я не всегда масштабируюсь ровно в 2 раза, и я блефую отразличные области img.Я передаю целые числа только для того, чтобы нарисовать изображение максимально четким.У меня также есть image-rendering:pixelated и другие варианты, определенные на холсте в CSS для масштабирования CSS, чтобы сохранить четкость.

Я знаю для своего конкретного примера, я мог бы просто увеличить масштаб img один раз и перемещаться вокругокончательный масштаб IMG, но это не вопрос.Вопрос в том, какой из них более производительный.Для моего приложения я должен масштабировать анимированную карту тайлов в каждом кадре, поэтому я перетаскиваю из нескольких источников на холст в пространстве 1: 1, а затем увеличиваю конечный холст от 30 до 60 раз в секунду, используя requestAnimationFrame.

В конце концов, они дают очень похожие результаты.CSS чуть более четкий и верный оригинальному изображению.CSS быстрее / эффективнее?Или масштабирование с drawImage более производительно?

ПРИМЕЧАНИЕ / РЕДАКТИРОВАНИЕ:

Я обнаружил, что если я использую режим стандартов с <!DOCTYPE html>, я должен передать строковые значения в style.width и style.height для метода CSS.Поэтому, если вы используете стандартный режим, убедитесь, что для них установлено "200px" вместо 200, иначе ваш холст не будет масштабироваться.

1 Ответ

1 голос
/ 23 сентября 2019

Canvas Alpha имеет значение

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

Отключить альфа холста с помощью const ctx = canvas.getContext("2d",{alpha: false})

Масштабирование не имеет значения

Для большинства устройств масштабирование отсутствует.более дорогая операция, чем рисование немасштабированного изображения.

Стоимость рендеринга зависит от количества прорисованных пикселей, а не от количества пикселей в источнике.

Оценка стоимости рендеринга

Стоимость drawImage

Если разрешение холста составляет 200 на 200, и вы рисуете изображение ctx.drawImage, которое заполняет его, то есть 40 000 пикселей, которые необходимо визуализировать.

Стоимость компоновки

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

Если холст имеет альфа-значение true, его необходимо объединить с фоном, поэтому стоимость рендеринга - это размер отображения холста в пикселях.

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

Стоимость рендерингапримеры

  • canvas - видимый элемент canvas
  • image - изображение, которое может поместиться в ОЗУ графического процессора

Лучше всего с выключенной альфа ибез CSS-масштабирования

canvas.width = canvas.height = 100;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d", {alpha: false});
ctx.drawImage(image, 100, 100);

// Total rendering cost 100 * 100 = 10,000 pixels

масштабирование с помощью CSS и выключение альфа-канала

canvas.width = canvas.height = 200;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d", {alpha: false});
ctx.drawImage(image, 200, 200);

// Total rendering cost 200 * 200 + 100 * 100 = 50,000 pixels

рендеринг с включенным альфа-управлением, без масштабирования CSS

canvas.width = canvas.height = 100;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d");  // alpha is on
// same as const ctx = canvas.getContext("2d", {alpha: true});
ctx.drawImage(image, 100, 100);

// Total rendering cost 100 * 100 + 100 * 100 = 20,000 pixels

Примечания

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