Есть два лучших претендента:
Создайте данные изображения 1 × 1, установите цвет и putImageData
укажите местоположение:
var id = myContext.createImageData(1,1); // only do this once per page
var d = id.data; // only do this once per page
d[0] = r;
d[1] = g;
d[2] = b;
d[3] = a;
myContext.putImageData( id, x, y );
Используйте fillRect()
для рисования пикселя (не должно быть проблем с наложением):
ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
ctx.fillRect( x, y, 1, 1 );
Вы можете проверить скорость их здесь: http://jsperf.com/setting-canvas-pixel/9 или здесь https://www.measurethat.net/Benchmarks/Show/1664/1
Я рекомендую тестировать на браузерах, которые вас интересуют, на максимальной скорости. По состоянию на июль 2017 года, fillRect()
Firefox v54 и Chrome v59 (Win7x64) работают в 5-6 раз быстрее.
Другие, более глупые альтернативы:
с помощью getImageData()/putImageData()
на всем холсте; это примерно в 100 раз медленнее, чем другие варианты.
Создание собственного изображения с использованием URL-адреса данных и использование его drawImage()
для отображения:
var img = new Image;
img.src = "data:image/png;base64," + myPNGEncoder(r,g,b,a);
// Writing the PNGEncoder is left as an exercise for the reader
создание другого img или холста, заполненного всеми пикселями, которые вы хотите использовать drawImage()
чтобы переместить только тот пиксель, который вы хотите. Это, вероятно, будет очень быстро, но имеет ограничение, которое необходимо предварительно рассчитать необходимые пиксели.
Обратите внимание, что мои тесты не пытаются сохранить и восстановить контекст холста fillStyle
; это замедлит fillRect()
производительность. Также обратите внимание, что я не начинаю с чистого листа и не тестирую один и тот же набор пикселей для каждого теста.
fillRect()
последнее время он стал почти в 10 раз быстрее, чем предполагаемые данные 1x1 на Chromev24. Так что ... если скорость критична и вы знаете свою целевую аудиторию, не верьте слову устаревшего ответа (даже моего). Вместо этого: тест!Один метод, который не был упомянут, использует getImageData и затем putImageData.
Этот метод хорош, если вы хотите рисовать много за один раз, быстро.
http://next.plnkr.co/edit/mfNyalsAR2MWkccr
источник
Я не учел
fillRect()
, но ответы подтолкнули меня к тому, чтобы сравниватьputImage()
.Помещение 100 000 случайно окрашенных пикселей в случайные места с Chrome 9.0.597.84 на (старом) MacBook Pro занимает менее 100 мс
putImage()
, но почти 900 мсfillRect()
. (Контрольный код на http://pastebin.com/4ijVKJcC ).Если вместо этого я выберу один цвет за пределами циклов и просто
putImage()
нанесу этот цвет в случайных местах, то 59 мс против 102 мс дляfillRect()
.Кажется, что накладные расходы на генерацию и анализ спецификации цвета CSS в
rgb(...)
большая часть различий синтаксисе.С
ImageData
другой стороны, размещение необработанных значений RGB в блоке не требует обработки или разбора строк.источник
источник
putImageData()
после этой функции или контекст будет обновляться по ссылке?Поскольку разные браузеры, похоже, предпочитают разные методы, может быть, имеет смысл провести меньший тест со всеми тремя методами в рамках процесса загрузки, чтобы выяснить, какой из них лучше всего использовать, а затем использовать его во всем приложении?
источник
Это кажется странным, но, тем не менее, HTML5 поддерживает рисование линий, кругов, прямоугольников и многих других базовых фигур, в нем нет ничего подходящего для рисования базовой точки. Единственный способ сделать это - смоделировать точку с тем, что у вас есть.
Таким образом, в основном есть 3 возможных решения:
У каждого из них есть свои недостатки
Линия
Имейте в виду, что мы движемся в юго-восточном направлении, и если это край, может возникнуть проблема. Но вы также можете рисовать в любом другом направлении.
Прямоугольник
или более быстрым способом, используя fillRect, потому что движок рендеринга просто заполнит один пиксель.
Круг
Одна из проблем с кругами заключается в том, что движку сложнее их визуализировать.
та же идея, что и с прямоугольником, которую вы можете реализовать с помощью fill.
Проблемы со всеми этими решениями:
Если вам интересно, «Как лучше всего нарисовать точку? », Я бы выбрал заполненный прямоугольник. Вы можете увидеть мой jsperf здесь со сравнительными тестами .
источник
Как насчет прямоугольника? Это должно быть более эффективным, чем создание
ImageData
объекта.источник
putImageData
его в 10 раз быстрее, чемfillRect
в Chrome. (Смотрите мой ответ больше.)Нарисуйте прямоугольник, как сказал sdleihssirhc!
^ - должен нарисовать прямоугольник 1x1 в x: 10, y: 10
источник
Хм, вы также можете просто сделать линию шириной 1 пиксель длиной 1 пиксель и сделать так, чтобы ее направление двигалось вдоль одной оси.
источник
Чтобы завершить Phrogz очень подробный ответ, есть критическая разница между
fillRect()
иputImageData()
.Сначала использует контекст , чтобы нарисовать над путем добавления прямоугольника (не пиксель), используя FillStyle значения альфа и контекст , globalAlpha и матрицу преобразования , линейные колпачки и т.д ..
Вторым заменяет весь набор пикселей (может быть один, но почему ?)
Результат отличается, как вы можете видеть на jsperf .
Никто не хочет устанавливать один пиксель за раз (то есть рисовать его на экране). Вот почему нет конкретного API для этого (и это правильно).
С точки зрения производительности, если целью является создание изображения (например, программного обеспечения для трассировки лучей), вы всегда хотите использовать массив, полученный с
getImageData()
помощью оптимизированного Uint8Array. Затем вы звонитеputImageData()
один раз или несколько раз в секунду, используяsetTimeout/seTInterval
.источник
fillRect
было болезненным, потому что ч / б ускорение Chrome не справляется с отдельными вызовами графического процессора, которые ему потребуются. В итоге мне пришлось использовать данные пикселей в пропорции 1: 1, а затем использовать масштабирование CSS, чтобы получить желаемый результат. Это некрасиво :(get/putImageData
операций в секунду , а 194 893 -fillRect
.1x1 image data
125,102 Ops / сек. Так чтоfillRect
, безусловно, побеждает в Firefox. Так что с 2012 года по сегодняшний день многое изменилось. Как всегда, никогда не полагайтесь на старые результаты тестов.Быстрый HTML-демонстрационный код: основе того, что я знаю о графической библиотеке SFML C ++:
Сохраните это как файл HTML с кодировкой UTF-8 и запустите его. Не стесняйтесь проводить рефакторинг, мне просто нравится использовать японские переменные, потому что они лаконичны и не занимают много места
Редко вы хотите установить один произвольный пиксель и отобразить его на экране. Так что используйте
метод рисования многочисленных произвольных пикселей в резервный буфер. (дешевые звонки)
Затем, когда будете готовы показать, позвоните
метод для отображения изменений. (дорогой звонок)
Полный код .HTML файла ниже:
источник
Если вы беспокоитесь о скорости, то вы также можете рассмотреть WebGL.
источник
HANDY и предложение из пут пикселя (рр) функции (ES6) (чтение пикселей здесь ):
Показать фрагмент кода
Эта функция используется
putImageData
и имеет часть инициализации (первая длинная строка). В начале вместоs='.myCanvas'
используйте CSS-селектор для вашего холста.Я хочу , чтобы вы нормализовать параметры значения от 0-1 вы должны изменить стандартное значение
a=255
дляa=1
и строки с:id.data.set([r,g,b,a]),ctx.putImageData(id, x, y)
доid.data.set([r*255,g*255,b*255,a*255]),ctx.putImageData(id, x*c.width, y*c.height)
Приведенный выше удобный код хорош для тестирования графических алгоритмов или для проверки концепции, но его не рекомендуется использовать в производстве, где код должен быть читаемым и понятным.
источник
putImageData
вероятно быстрее чемfillRect
изначально. Я думаю, что это потому, что пятый параметр может иметь различные способы назначения (цвет прямоугольника), используя строку, которая должна быть интерпретирована.Предположим, вы делаете это:
Итак, линия
самый тяжелый из всех. Пятый аргумент в
fillRect
вызове - это более длинная строка.источник
context.fillStyle = ...
вместо этого. developer.mozilla.org/en-US/docs/Web/API/...