ПРИМЕЧАНИЕ . Это связано с тем, как существующие элементы холста отображаются при увеличении масштаба , а не в том, как линии или графика отображаются на поверхности холста . Другими словами, это есть всечтобы сделать с интерполяцией из масштабируемых элементов , и ничего общего с сглаживанием графической втягивается на холсте. Меня не волнует, как браузер рисует линии; Я забочусь о томкак браузер делает холст элементу себя , когда она масштабируется до.
Есть ли свойство холста или параметр браузера, который я могу изменить программно, чтобы отключить интерполяцию при масштабировании <canvas>
элементов? Кроссбраузерное решение идеально, но не обязательно; Моя основная цель - браузеры на основе Webkit. Производительность очень важна.
Этот вопрос наиболее похож, но недостаточно иллюстрирует проблему. Как бы то ни было, я безуспешно пытался image-rendering: -webkit-optimize-contrast
.
Приложение будет представлять собой 8-битную игру в стиле «ретро», написанную на HTML5 + JS, чтобы было понятно, что мне нужно.
Для иллюстрации приведу пример. ( живая версия )
Допустим, у меня холст 21х21 ...
<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 */
Я рисую простой крестик на холсте, вот так:
$('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). Изображение справа - это то, что я хочу (нарисовано от руки в иллюстративных целях).
источник
Ответы:
Последнее обновление: 12.09.2014
Ответ может быть когда-нибудь . На данный момент вам придется прибегнуть к хитростям, чтобы получить то, что вы хотите.
image-rendering
В рабочем проекте CSS3 намечено новое свойство,
image-rendering
которое должно делать то, что я хочу:Спецификация описывает одно из следующих значений:
auto
,crisp-edges
, и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, является:
К сожалению, это пока не работает на всех основных платформах HTML5 (в частности, в Chrome).
Конечно, можно вручную масштабировать изображения с помощью интерполяции ближайшего соседа на поверхности холста с высоким разрешением в javascript или даже предварительно масштабировать изображения на стороне сервера, но в моем случае это будет слишком дорого, поэтому это не жизнеспособный вариант.
ImpactJS использует технику предварительного масштабирования текстуры, чтобы обойти весь этот FUD. Разработчик Impact, Доминик Саблевски, написал об этом очень подробную статью (в конечном итоге он даже процитировал этот вопрос в своем исследовании).
См . Ответ Саймона о решении на основе холста, которое зависит от
imageSmoothingEnabled
свойства (недоступно в старых браузерах, но проще, чем предварительное масштабирование, и поддерживается довольно широко).Живая демонстрация
Если вы хотите протестировать свойства CSS, обсуждаемые в статье MDN об
canvas
элементах, я сделал эту скрипку, которая должна отображать что-то вроде этого, размыто или нет, в зависимости от вашего браузера:источник
Новый ответ 31.07.2012
Это наконец-то в спецификации холста!
Спецификация недавно добавила свойство, называемое по
imageSmoothingEnabled
умолчаниюtrue
и определяющее, будут ли изображения, нарисованные в нецелочисленных координатах или масштабированные, использовать более плавный алгоритм. Если для него установлено значение, используетсяfalse
ближайший сосед, создавая менее гладкое изображение и вместо этого просто делая пиксели большего размера.Сглаживание изображений только недавно было добавлено в спецификацию холста и поддерживается не всеми браузерами, но в некоторых браузерах реализованы версии этого свойства с префиксом поставщика. В контексте существует
mozImageSmoothingEnabled
в Firefox, а такжеwebkitImageSmoothingEnabled
в Chrome и Safari, и установка для них значения false остановит сглаживание. К сожалению, на момент написания IE9 и Opera не реализовали это свойство, с префиксом поставщика или иным образом.Предварительный просмотр: JSFiddle
Результат:
источник
Изменить 31.07.2012 - Эта функция теперь включена в спецификацию холста! См. Отдельный ответ здесь:
https://stackoverflow.com/a/11751817/154112
Старый ответ ниже для потомков.
В зависимости от желаемого эффекта у вас есть один вариант:
http://jsfiddle.net/wa95p/
Что создает это:
Наверное, не то, что вы хотите. Но если бы вы просто хотели получить нулевое размытие, то это было бы правильным решением, поэтому я предлагаю его на всякий случай.
Более сложный вариант - использовать манипуляции с пикселями и самостоятельно написать алгоритм для работы. Каждый пиксель первого изображения становится блоком пикселей 5x5 на новом изображении. Это было бы несложно сделать с изображениями.
Но сами по себе Canvas и CSS не помогут вам в масштабировании одного изображения до другого с желаемым эффектом.
источник
image-rendering: -webkit-optimize-contrast
должен помочь, но, похоже, ничего не делает. Я могу рассмотреть возможность развертывания функции для масштабирования содержимого холста с использованием интерполяции ближайшего соседа.В Google Chrome шаблоны изображений холста не интерполируются.
Вот рабочий пример, отредактированный из ответа namuol http://jsfiddle.net/pGs4f/
источник
Обходной путь Сависки объяснен здесь является перспективным, так как он работает на:
Но не работает в следующем, но того же эффекта можно добиться с помощью рендеринга изображений CSS:
Проблема заключается в следующем, потому что ctx.XXXImageSmoothingEnabled не работает и рендеринг изображений не работает:
источник