Мультимедиа
Графические элементы: Img, Svg и Canvas (и немного CSS)
Знаю, вам, вероятно, не терпится прочесть разделы этой лекции, посвященные аудио и видео, но мы не можем забывать о том, что изображения были основой веб-приложений с самого начала и их важность в реализации опыта взаимодействия пользователя и приложения все еще огромна. Действительно, полезно помнить о том, что видео, концептуально, это лишь последовательный набор статических изображений, быстро сменяющих друг друга! К счастью, HTML5 значительно расширил возможность приложений по включению в себя графических данных путем добавления поддержки формата SVG и элемента canvas к проверенному временем элементу управления img. Кроме того, применение CSS-анимаций и переходов (этому посвящена "Целенаправленная анимация" ) к элементам изображений, которые иначе неподвижны, позволяет сделать их очень динамичными.
Говоря о CSS, важно отметить, что многие графические эффекты, которые раньше требовали применения соответствующим образом подготовленного статического изображения, могут быть реализованы только с использованием CSS, в частности, с применением CSS3:
- Границы, фоновые цвета, фоновые изображения.
- Изображения закладок папок, меню, панели инструментов.
- Скругленные углы границ, использование нескольких границ и фонов, границы изображений
- Прозрачность
- Встраиваемые шрифты
- Тени объектов
- Тени текстов
- Градиенты
Коротко говоря, если вы когда-либо использовали элементы img для создания маленьких визуальных эффектов, создания градиентных фонов, использования нестандартного шрифта или создания графических элементов навигации, теперь есть возможность сделать это исключительно с помощью CSS. Для того, чтобы узнать подробности, обратитесь к отличному материалу по CSS3 (http://coding.smashingmagazine.com/2009/01/08/push-your-web-design-into-the-future-with-css3/) от Smashing Magazine и к спецификациям CSS3 на http://www.w3.org/. CSS так же предоставляет возможность декларативно обрабатывать некоторые события и визуальные состояния с использованием псевдо-селекторов для hover, visited, active, focus, target, enabled, disabled, и checked. Для того, чтобы узнать подробности, обратитесь к материалам ресурса http://css-tricks.com/ и к еще материалу Smashing Magazine по псевдо-классам (http://coding.smashingmagazine.com/2011/03/30/how-to-use-css3-pseudo-classes/).
Рассмотрим теперь три основные HTML5-элемента для вывода изображений:
- Элемент img используется для растровых изображений. Формат PNG предпочтителен по сравнению с другими, особенно для текстов и штриховых рисунков, хотя JPEG-файлы фотографий имеют меньший размер. GIF, как правило, считается устаревшим, в тех случаях, когда использование GIF-файлы давало выигрыш за счет маленького размера, теперь можно пользоваться исключительно CSS. Если речь идет о масштабировании, приложения для Магазина Windows должны учитывать плотность пикселей, как мы видели в лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", и предоставлять различные файлы изображений ля каждого масштаба, с которым может столкнуться приложение. Это тот случай, когда JPEG-файлы меньшего размера могут уменьшить общий размер пакета приложения в Магазине Windows.
- Формат SVG лучше всего использовать для плавного масштабирования изображений на мониторах разного размера и разной плотности пикселей. SVG-изображения могут быть описаны внутри HTML-кода, созданы динамически в DOM, ими можно управлять как отдельными файлами и использовать в качестве источника для элемента img (в этом случае все характеристики масштабирования поддерживаются). SVG-файл так же может быть использован как источник для iframe, что дает преимущества в виде доступности дочерних элементов SVG в DOM. Как мы видели в лекции 6 курса "Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript", сохранение соотношения сторон SVG-изображения часто важно, для чего мы использовали viewBox и атрибуты preserveAspectRatio тега svg.
- Элемент canvas (холст) предоставляет поверхность для рисования и API для создания изображений с использованием линий, прямоугольников, дуг, текста и так далее. Холст, в итоге, генерирует растровые данные, что означает, что будучи однажды созданным, такое изображение масштабируется как растровое. (Приложение, конечно, обычно перерисовывает холст с масштабированием координат для того, чтобы избежать пикселизации). Холст весьма полезен для выполнения манипуляций с пикселями, даже с отдельными кадрами видео, когда оно проигрывается.
Приложения часто используют все три элемента, опираясь на их сильные стороны. Я говорю это, так как, когда элемент canvas впервые стал доступен, разработчики оказались так им очарованы, что, казалось, забыли, как пользоваться img и они игнорируют тот факт, что часто SVG – это наилучший вариант! (И я ведь уже сказал, что CSS сам по себе способен на многое, а?)
В конце концов, полезно полезно воспринимать все графические элементы HTML5 как производящие, в конечно счете, растровые изображения, которые хост приложения просто выводит на экран. Вы можете, конечно, программно анимировать внутреннее содержимое этих элементов в JavaScript, как мы увидим в "Целенаправленная анимация" , но для наших целей полезно просто думать о них как о статических, по сути, изображениях.
Что отличает эти элементы друг от друга, так это то, как в них поступают данные. Элементы img загружают данные из файла-источника, svg-данные заданы в разметке, элементы canvas заполняются посредством программного кода. Но, в конце концов, как показано в Сценарии 1 упражнения "Графика в HTML" для этой лекции, и как отражено на рис. 5.1 все они производят одинаковые результаты:
Коротко говоря, в том, что может быть выведено с помощью каждого из элемента, нет фундаментальных различий. Тем не менее, у них есть различия, которые становятся очевидными, когда мы начинаем манипулировать этими элементами как и в случае с CSS. Так каждый элемент – это лишь узел в DOM, простой и ясный, и они рассматриваются как и все другие, неграфические элементы: CSS не влияет на внутреннее содержимое элементов, а влияет лишь на то, как они, в итоге, отображаются на странице. Отдельные части SVG, объявленные в разметке, могут, на самом деле, быть отдельно стилизованы до тех пор, пока их можно идентифицировать с помощью CSS-селекторов. В любом случае, подобная стилизация влияет только на внешний вид, таким образом, если применяются новые стили, они применяются к исходному содержимому элемента.
Справедливо и то, что графические элементы могут перекрывать друг друга и неграфические элементы (как и видео), и подсистема визуализации автоматически обрабатывает прозрачность в соответствии с параметром z-index этих элементов. Каждый графический элемент может иметь чистые, или прозрачные области, которые встроены в форматы изображений наподобие PNG. В элементе canvas, любые области, очищенные с помощью метода clearRect, которые иным образом не затрагивают другие вызовы API, будут прозрачными. Похожим образом, любая область прямоугольного элемента SVG, которая не затронута его отдельными частями, будет прозрачной.
Сценарий 2 в упражнении "Графика в HTML" позволяет вам включать несколько стилей (с помощью флагов) для тех же элементов, которые показаны ранее. В данном случае я сделал фон элемента canvas прозрачным, таким образом, мы можем видеть то, что распложено за ним. Когда стили применяются, элемент img оказывается повернутым и трансформированным, к canvas применяется масштабирование, и отдельные части svg-элемента стилизуются новыми цветами, как показано на рис. 5.2.
Рис. 5.2. Стили, примененные к графическим элементам; отдельные элементы SVG могут быть стилизованы, если они доступны посредством DOM
Стили, заданные в css/scenario2.css, довольно просты:
.transformImage { transform: rotate(30deg) translateX(120px); } .scaleCanvas { transform: scale(1.5, 2); }
Как и код в js/scenario2.js, который их применяет:
function toggleStyles() { var applyStyles = document.getElementById("check1").checked; document.getElementById("image1").className = applyStyles ? "transformImage" : ""; document.getElementById("canvas1").className = applyStyles ? "scaleCanvas" : ""; document.getElementById("r").style.fill = applyStyles ? "purple" : ""; document.getElementById("l").style.stroke = applyStyles ? "green" : ""; document.getElementById("c").style.fill = applyStyles ? "red" : ""; document.getElementById("t").style.fontStyle = applyStyles ? "normal" : ""; document.getElementById("t").style.textDecoration = applyStyles ? "underline" : ""; }
Другая особенность, которую вы могли заметить при применении стилей, это то, что увеличенный элемент canvas выглядит пикселизованным, как обычно бывает с растровыми изображениями. Это вполне ожидаемое поведение, как показано в следующей таблице о характеристиках масштабирования. Это показано в Сценариях 3 и 4 упражнения "Графика в HTML".
Элемент | Масштабирование | Обработка изменений макета для лучшего отображения |
---|---|---|
img | растеризованное | Измените атрибут src для различных масштабов (или просто используйте SVG-файл в качесте источника). |
canvas | растеризованное | Перерисуйте холст с использованием масштабированных размеров; часто это можно сделать наилучшим образом, вызвав <context>.scale в соответствии с необходимым размером отображения вместо изменения координат, использованных в коде |
svg | плавное | Нет необходимости. Используйте viewBox и preseveAspectRatio для пропорционального изменения масштаба. |
Дополнительные характеристики графических элементов
Существуют некоторые дополнительные характеристики, о которых следует знать, работая с графическими элементами. Во-первых, это разные виды операций, которые вызывают перерисовку элементов в документе. Во-вторых, это режим работы каждого элемента. В-третьих – это относительные преимущества каждого элемента. Все это приведено в следующей таблице:
Элемент | Операции, вызывающие перерисовку | Режим | Преимущества |
---|---|---|---|
img | Изменение атрибута src Изменение стиля из JavaScript | Пиксельный |
Быстро выводится и трансформируется Отлично подходит для статических элементов и статических/повторяющихся фонов Возможна спрайтовая анимация путем изменения атрибута src |
canvas |
Вызов контекстного API Изменение стиля из JavaScript Обратите внимание: перерисовка происходит только тогда, когда код возвращает управление хост-процессу и разблокирует поток пользовательского интерфейса. Когда код манипулирует элементом, видимых изменений не наблюдается. |
Немедленный: вызовы API приводят к выводу пикселей и не запоминаются |
Качественный динамический контент Быстро выводится после перерисовки Возможность манипуляции изображением на уровне пикселей Отлично подходит для качественного динамического/интерактивного содержимого с частым использованием вычислений. |
svg |
Изменение структуры элемента Изменение стиля из JavaScript |
С запоминанием: все фигуры существуют как элементы DOM (если не используется в атрибуте img src) |
Плавное масштабирование Точное управление отдельными (запоминаемыми) элементами Возможность манипуляции на уровни фигур Отлично подходит для интерактивной графики, детализированной и масштабируемой стилизации, и динамической настройки атрибут отдельных фигур |
Так как SVG создает элементы в DOM, эти элементы могут быть стилизованы индивидуально. Вы можете использовать этот факт вместе с медиа-запросами для скрывать разные части SVG в зависимости от их размера. Для того, чтобы сделать ээто, добавьте различные классы к таким SVG-элементам, затем, в CSS, добавьте или удалите стиль display: none для этих классов в медиа-запросах наподобие @media (min-width:300px) and (max-width:499px) . Вам может понадобиться рассчитать размер SVG по отношению к окну приложения, но это означает, что вы можете эффективно убрать детали из SVG вместо того, чтобы позволять этим частям отрисовываться на слишком малом пространстве, чтобы быть полезными.
В итоге, причина по которой HTML5 имеет все три элемента, заключается в том, что все три по-настоящему нужны. Все они способны получить преимущества от полного аппаратного ускорения, так же, как это происходит в Internet Explorer, так как приложения, написанные на HTML и JavaScript исполняются на той же подсистеме визуализации, что и браузер.
Лучший подход к дизайну приложений – по-настоящему исследовать подходящие варианты использования элементов каждого типа. Каждый элемент может иметь прозрачные области, в итоге, вы можете легко достигнуть весьма забавных эффектов. Например, если у вас есть данные, которые выводят временную информацию о видео или другой текст, в надпись, вы можете просто использовать обработчик интервалов (с интервалом, установленным на необходимую детализации, пол секунды, например), получить свойство видео currentTime, получить необходимый текст для данного фрагмента, и вывести текст на пэлементе canvas c прозрачным фоном, который расположен поверх видео. Субтитры и другие сведения о видео можно вывести похожим образом, устраняя необходимость в перекодировании видео.