Отключить интерполяцию при масштабировании
Примечание: это как существующие элементы холста отображаются при масштабировании,не чтобы сделать с тем, как линии или графика отображаются на поверхность холста. Другими словами, это имеет все отношение к интерполяция на масштабирование элементов и ничего общего с антиалиасинг графики рисуются на холсте. Меня не волнует, как браузер рисует lines; я забочусь о том, как браузер отображает элемент canvas когда он увеличивается.
есть ли свойство холста или настройки браузера, которые я могу изменить программно, чтобы отключить интерполяцию при масштабировании <canvas> элементов? Кросс-браузерное решение идеально, но не обязательно; браузеры на основе Webkit-моя главная цель. Производительность очень важна.
этот вопрос наиболее похож, но не иллюстрирует проблему достаточно. Для чего это стоит, я уже пробовал image-rendering: -webkit-optimize-contrast безрезультатно.
приложение будет "ретро" 8-битной стилизованной игрой, написанной на HTML5+JS, чтобы понять, что мне нужно.
чтобы проиллюстрировать, приведу пример. (концертная версия)
Предположим, у меня есть холст 21x21...
<canvas id='b' width='21' height='21'></canvas>
...который имеет css, что делает элемент в 5 раз больше (105x105):
canvas { border: 5px solid #ddd; }
canvas#b { width: 105px; height: 105px; } /* 5 * 21 = 105 */
Я рисую простой ' X ' на холсте, как Итак:
$('canvas').each(function () {
var ctx = this.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(21,21);
ctx.moveTo(0,21);
ctx.lineTo(21,0);
ctx.stroke();
});
изображение слева-это то, что отображает Chromium (14.0). Изображение справа-это то, что я хочу (рисованной иллюстрации).


5 ответов:
Последнее Обновление: 2014-09-12
есть ли свойство холста или настройки браузера, которые я могу изменить программно, чтобы отключить интерполяцию при масштабировании элементов?
ответ может быть когда-нибудь. На данный момент вам придется прибегнуть к хакерским обходам, чтобы получить то, что вы хотите.
image-renderingрабочий проект CSS3 описывает новое свойство,
image-renderingчто должен делать то, что я хочу:свойство визуализации изображения предоставляет подсказку агенту пользователя о том, какие аспекты изображения наиболее важны для сохранения при масштабировании изображения, чтобы помочь агенту пользователя в выборе соответствующего алгоритма масштабирования.
спецификация описывает три значения:
auto,crisp-edgesиpixelated.pixelated:
когда при масштабировании изображения вверх необходимо использовать" ближайший сосед " или аналогичный алгоритм, чтобы изображение выглядело просто состоящим из очень больших пикселей. При уменьшении масштаба это то же самое, что и авто.
стандартные? Кросс-браузер?
так как это просто рабочий проект, нет никакой гарантии, что это станет стандартом. Поддержка браузера в настоящее время пятнистый, в лучшем случае.
сеть разработчиков Mozilla имеет довольно тщательная страница, посвященная текущему состоянию искусства который я настоятельно рекомендую прочитать.
разработчики Webkit изначально выбрали ориентировочно реализовать это как
-webkit-optimize-contrast, но Chromium/Chrome, похоже, не использует версию Webkit, которая реализует это.обновление: 2014-09-12
Chrome 38 теперь поддерживает
image-rendering: pixelated!Firefox имеет сообщить об ошибке открыть в получить
image-rendering: pixelatedреализованы, но-moz-crisp-edgesработает.решение?
самое кросс-платформенное, CSS-единственное решение до сих пор таково:
canvas { image-rendering: optimizeSpeed; /* Older versions of FF */ image-rendering: -moz-crisp-edges; /* FF 6.0+ */ image-rendering: -webkit-optimize-contrast; /* Safari */ image-rendering: -o-crisp-edges; /* OS X & Windows Opera (12.02+) */ image-rendering: pixelated; /* Awesome future-browsers */ -ms-interpolation-mode: nearest-neighbor; /* IE */ }к сожалению, это не будет работать на всех основных платформах HTML5 еще (Chrome, в частности).
конечно, можно вручную масштабировать изображения с помощью интерполяции ближайших соседей на поверхности холста высокого разрешения в javascript или даже предварительно масштабировать изображения на стороне сервера, но в моем случае это будет запретительно дорого, так что это не жизнеспособный вариант.
ImpactJS использует метод предварительного масштабирования текстуры, чтобы обойти все это FUD. Разработчик Impact, Dominic Szablewski,написал очень глубокую статью об этом (он даже привел этот вопрос в своем исследовании).
посмотреть Симона для решения на основе холста, которое опирается на
imageSmoothingEnabledсвойство (недоступно в старых браузерах, но проще, чем предварительное масштабирование и довольно широко поддерживается).Демо
если вы хотите проверить свойства CSS, описанные в статье MDN на
canvasэлементы, я составила эта скрипка, который должен показывать что-то вроде этого, размыто или нет, в зависимости от Вашего браузера:
новый ответ 31.07.2012
это, наконец, в спецификации холста!
спецификация недавно добавила свойство под названием
imageSmoothingEnabledзначение по умолчанию:trueи определяет, будут ли изображения, нарисованные по нецелым координатам или нарисованные в масштабе, использовать более плавный алгоритм. Если он установлен вfalseзатем используется ближайший сосед, создавая менее гладкое изображение и вместо этого просто делая более крупные пиксели.сглаживание изображения только недавно был добавлен в спецификацию canvas и не поддерживается всеми браузерами, но некоторые браузеры реализовали версии этого свойства с префиксом поставщика. В контексте существует
mozImageSmoothingEnabledв Firefox иwebkitImageSmoothingEnabledв Chrome и Safari, и установка их в false остановит сглаживание от возникновения. К сожалению, на момент написания статьи IE9 и Opera не реализовали это свойство, префикс поставщика или иначе.
предварительный просмотр: JSFiddle
результат:
Edit 7/31/2012 - эта функция теперь находится в спецификации canvas! Смотрите ответ здесь:
https://stackoverflow.com/a/11751817/154112
старый ответ ниже для потомков.
в зависимости от вашего желаемого эффекта, у вас есть это как один вариант:
var can = document.getElementById('b'); var ctx = can.getContext('2d'); ctx.scale(5,5); $('canvas').each(function () { var ctx = this.getContext("2d"); ctx.moveTo(0,0); ctx.lineTo(21,21); ctx.moveTo(0,21); ctx.lineTo(21,0); ctx.stroke(); });который создает это:
наверное, не то, что ты хочешь. Но если бы вы просто хотели иметь нулевое размытие, то это был бы билет, поэтому я предложу его на всякий случай.
более сложный вариант-использовать манипуляции пикселей и записать алгоритм для работы. Каждый пиксель первого изображения становится блоком пикселей 5x5 на новом изображении. Это было бы не слишком сложно сделать с imagedata.
но холст и CSS сами по себе не помогут вам здесь для масштабирования одного к другому с точным эффектом, который вы хотите.
в google chrome шаблоны изображений canvas не интерполируются.
вот рабочий пример, отредактированный из ответа namuol http://jsfiddle.net/pGs4f/
ctx.scale(4, 4); ctx.fillStyle = ctx.createPattern(image, 'repeat'); ctx.fillRect(0, 0, 64, 64);
обходной путь Сависки эксплицируется здесь перспективен, потому что он работает на:
- Chrome 22.0.1229.79 Mac OS X 10.6.8
- Chrome 22.0.1229.79 m Windows 7
- Chromium 18.0.1025.168 (Developer Build 134367 Linux) Ubuntu 11.10
- Firefox 3.6.25 Windows 7
но не работает в следующем, но тот же эффект может быть достигнут с помощью CSS рендеринг изображений:
- Firefox 15.0.1 Mac OS X 10.6.8 (рендеринг изображений: - moz-crisp-Edge работает в этой)
- Opera 12.02 Mac OS X 10.6.8 (рендеринг изображений:-o-crisp-Edge работает в этой)
- Opera 12.02 Windows 7 (рендеринг изображений: - o-crisp-Edge работает в этой)
проблематично это, потому что ctx.XXXImageSmoothingEnabled не работает и рендеринга изображений нет рабочий:
- Safari 5.1.7 Mac OS X 10.6.8. (рендеринг изображений: - webkit-оптимизация-контраст не работает)
- Safari 5.1.7 Windows 7 (рендеринг изображений: - webkit-оптимизация-контраст не работает)
- IE 9 Windows 7 (- ms-интерполяция-режим: ближайший сосед не работает)



Comments