Глубокое погружение в Canvas


Содержание

10 крутых примеров работы HTML5 Canvas

Холст — интересная особенность в HTML5 Canvas которая позволяет рисовать разнообразные вещи в браузере с помощью технологии Java. Например его можно использовать для управления фотографий, рисовать и анимировать разнообразные формы и фигуры, а так же воспроизводить видео. Но это ещё далеко не придел.

По этому, чтобы продемонстрировать на что возможна HTML5, тут представлена небольшая подборка различных и красивых примеров, которые точно Вам понравятся.

Радужный дождь

Действительно удачный пример анимации работающей на HTML5 Canvas, как будто с неба льёт радужный дождь. Очень красиво смотрится.

Частицы

Интересный эффект на HTML5 Canvas, который имитирует движение мелких частиц из букв, очень красивая и своеобразная анимация, которую можно использовать практически на любых сайтах.

Анимированные круги

Интересный и не сильно сложный эффект работающий на HTML5 Canvas. Тут несколько кругов, которые плавно меняют свою форму, таким образом получается красивый визуальный эффект.

Геометрическая анимация

Ну что сказать, это потрясающий и красивый эффект геометрической анимации на которую можно смотреть вечно, так как выгляди это очень здорово.

Анимационные шары

Плавно двигающиеся шары, замечательный пример который можно сделать на HTML5 Canvas. Этот эффект будет круто и современно смотреться на большинства сайтах.

Созвездие

Тут созданы случайно двигающиеся звёзды, а при наведении мыли они соединяются линиями. Очень красиво сделанное демо.

Молния

Отличная и удачная имитация молнии с помощью HTML5 Canvas. Смотрится очень достойно и потрясающе!

Радужный осьминог

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

Найди курсор

Этот пример отслеживает расположение курсора указывая на него стрелками

Механическая трава

Интересный пример, который реагирует на движения курсора, дорисовывая линии. Очень интересно и необычно придумано.

Техника глубокого мышечного расслабления

Уникальная и универсальная техника расслабления, проверенная годами практики. Большинство моих клиентов применяют данную технику.

Итак, начнем с главного. Вот описание самой последней версии техники: Психологическая техника: Глубокое Погружение в тело. Версия 2012.

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

Сегодня в телесно-ориентированной психотерапии общепризнано, что исцеление от телесных недугов может быть достигнуто путем проработки породивших их психологических причин. Исследуя телесные проявления, можно дойти до глубин души человека, разгадать тайны подсознания, добраться до скрытого смысла сил, движущих человеком. Взаимодействуя с подсознанием, мы имеем шанс использовать скрытые в его глубинах внутренние психологические ресурсы.

Глубокое мышечное расслабление оказывает непосредственное физическое воздействие, начиная от простого мышечного расслабления и до активации всей иммунной системы организма. Она помогает достичь эмоционального и душевного равновесия, освобождает внутренние силы и улучшает общее самочувствие человека.

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

Нужно отметить, что эта статья признана Лучшей статьей 2012 года

Предназначение техники – снятие внутренних зажимов (последствия психологических травм и неблагоприятного прошлого опыта. Исходя из того, что любое деструктивное в человеке является следствием недостатка (неразвитости) конструктивного, можно сказать, что техника является универсально и позволяет самостоятельно работать с любыми проблемами, которыми вообще занимается психология. Приводя человека к более полноценной психологической жизни, эта техника тем самым выводит его из замкнутого круга проблем.

Есть вариант работы с техникой погружения в тело – в паре с партнером. На определенном этапе, это позволяет сдвинуть дело с «мертвой точки».Психосоматический массаж. Второе издание статьи «Как делают сказку»,

Введение в Canvas

В этой статье мы познакомим вас c новым элементом HTML5 — canvas, который позволяет рисовать различные объекты и отображать в самых современных браузерах. Прочитав данный урок, вы узнаете, как получить доступ к элементу canvas, рисовать фигуры, изменять цвета, и стирать объекты. Приобретайте путёвку в современный мир Web технологий.

Я надеюсь, вам понравится эта серия уроков. Она рассчитана на тех, кто имеет какой-то опыт работы в JavaScript, и совсем ничего не знает насчёт элемента canvas. Если вы новичок в JavaScript, не переживайте, вы приобретёте некоторые знания, прочитав данную статью.

Знакомимся с элементом Canvas

Использовать элемент canvas очень просто

Когда вы слышите слово canvas, то вы сразу же думаете о новом HTML5 элементе с одноимённым названием. Технически, это только половина всей правды, но давайте не будем сейчас говорить об этом. Элемент canvas — это нововведение для всех браузеров.

Для того чтобы воспользоваться элементом canvas, необходимо просто создать соответствующий HTML тег, а затем определить ширину и высоту.

Но это конечно же далеко не всё. Код, написанный выше поместит на вашу страницу canvas с прозрачным фоном. Внимание: контент внутри тега canvas будет отображён только в том случае, если ваш браузер является устаревшим и не поддерживает данную функциональность.

Поддержка

Этот элемент только для самых современных браузеров

Должен отметить, что самые современные браузеры поддерживают данный элемент, даже последний Internet Explorer.

  • Internet Explorer (9.0+)
  • Safari (3.0+)
  • Firefox (3.0+)
  • Chrome (3.0+)
  • Opera (10.0+)
  • iOS (1.0+)
  • Andro >К слову сказать, вы можете активировать данный элемент и в ранних версиях Internet Explorer при помощи данного плагина – Explorer Canvas.

Размеры элемента Canvas

В примере, расположенном выше вы уже увидели как применять атрибуты ширины и высоты: width и height. Используя CSS, вы также можете контролировать размеры canvas, как и других HTML элементов. И это вполне логично. Однако так как canvas использует в своём функционале так называемый двумерный контекст, то при применении CSS к размерам холста, приведёт к тому, что все внутренние элементы будут искажены.

Немного о двумерном контексте

Немного выше я сказал, что элемент canvas — это только половина всей истории. Вторая половина — это как раз и есть двумерный контекст, который по сути позволяет вам видеть и всю мощь функционала данного элемента.

Давайте расставим всё на свои места: когда мы используем элемент canvas, то фактически он не помещается на страницу. Вместо него вы получаете рисунок, который формируется в двумерном контексте, а доступ к этому рисунку осуществляется как раз через элемент canvas благодаря JavaScript API. В принципе кому-то эта информация может показаться лишней, однако лишние знания вам не повредят.

Система координат

Если вы когда-либо работали с языками, имеющими дело с 2d графикой (такими как ActionScript, Processing, и т.д.), тогда вы знаете всё о системах координат, основанных на движении. Двумерный контекст в элементе canvas ничем не отличается от перечисленных систем. Он использует стандартную систему координат Cartesian, с начальной точкой (0, 0), расположенной с левой верхней стороны. Движение вправо будет увеличивать значение объекта по оси x, в то время как движение вниз, будет увеличивать значения точек объекта по оси y. Всё довольно примитивно.

Одна единица данной системы координат равняется одному пикселю вашего экрана (в большинстве случаев).

Получение доступа к двумерному контексту

Для того чтобы получить доступ к двумерному контексту, вам понадобится применить JavaScript API. В данном случае, вам потребуется функция getContext. Пример:

Заметьте: в этом примере мы применяем jQuery, но только после того, как страница полностью загрузится. Для этих целей вы можете в полной мере пользоваться вашим любимым JavaScript фрэймворком или поместить скрипт в конец документа.

В результате вызова метода getContext, переменная ctx теперь будет ссылаться на двумерный контекст. Это означает, что теперь при помощи этой переменной вы можете начать рисовать фигуры на элементе canvas. Круто, да?!

Рисуем квадраты

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

Добавьте следующий код, используя переменную ctx, о которой мы говорили перед этим:

Этот код нарисует чёрный квадрат в левой верхней стороне холста. Примерно вот так вот:

Поздравляю! Вы только что нарисовали вашу первую фигуру в HTML5 элементе canvas. Каковы ощущения?

Заметьте: вы скорее всего уже смекнули, что на самом деле для рисования квадрата используется JavaScript. Это происходит потому, что в функциональности элемента canvas не предусматривается подобного метода (для рисования квадрата). На самом деле квадрат — это тот же самый прямоугольник, у которого все стороны равны.

В методе fillRect может быть прописано 4 параметра:

  • Первый — это позиция по оси x;
  • Второй — это позиция по оси y;
  • Третий — это параметр, отвечающий за ширину;
  • Четвёртый — это высота.

Если расписать прототип метода в псевдокоде, то он будет выглядеть следующим образом:

Хорошая новость заключается в том, что вы не ограничены в функционале, касающемся заливки. Уточню. Вы можете рисовать прямоугольник с прозрачной заливкой и цветной рамкой.Для этого в JavaScript API предусмотрена специальная функция strokeRect:

Данная функция принимает такой же набор аргументов, как и fillRect. В результате вы получите ещё один квадрат:

Просто. Элегантно. И ещё раз просто! Теперь вы поняли принцип, по которому работает элемент canvas. Все остальные методы подобны этим двум. Их использовать так же просто. Если вам кажется это чем-то примитивным, то не переживайте. Все эти элементы в совокупности могут творить чудеса.

Рисование по схеме

Помимо прямоугольников (которые могут быть нарисованы одним методом из API), вы так же можете рисовать фигуры по собственной схеме. Благодаря схемам вы можете создавать прямые или изогнутые линии, а так же более сложные фигуры.

Чтобы создать полноценную схему, вам необходимо будет воспользоваться следующими методами из API:

  • beginPath: начало схемы;
  • moveTo: метод для создания точки;
  • lineTo: рисует линию от точки до точки, которые были созданы методом moveTo, или до точки от прошлой линии, нарисованной методом lineTo;
  • closePath: завершить схему.
  • fill: заполнить фигуру цветом.
  • stroke: создать контур.

Попробуйте следующий пример:

Данный код нарисует треугольник чёрного цвета:


Те же самые принципы вы можете использовать для рисования фигур, которые вам понадобятся. В следующем уроке, посвящённом данной теме, мы поговорим о более продвинутом рисовании фигур, таких как овалы, кривая Безье и др.

Стоит сказать об этом именно сейчас: рисование по схеме применяется для создания более сложных фигур чем прямоугольники.

Изменение цветов

Итак, всё что мы рисовали до сих пор, будь то прямоугольник или треугольник, окрашивалось в чёрный цвет. Круто! Однако, существует множество функций в JavaScript API, которые позволят вам с лёгкостью изменить цвет фигуры, которую вы рисуете. Вашему вниманию представляю fillStyle и strokeStyle.

Объявлять тут в принципе нечего, поэтому давайте сразу же применим их на практике:

Данный код окрасит квадрат в красный цвет:

Или вы можете изменить цвет рамки квадрата:

Вот вы и научились применять данные методы:

Методы fillStyle и strokeStyle удобны тем, что они используют те же цвета, что и в привычном вам CSS. Это значит, что вы можете использовать RGB, RGBA, HSA, специальные слова (“red”) и шестнадцатеричные значения.

Сразу стоит отметить, что изменение цвета не приводит к преобразованию уже существующего содержания элемента canvas. К примеру, если вы нарисовали черный прямоугольник, затем создали наполнитель для красного цвета, а потом нарисовали ещё один прямоугольник, то первая фигура останется чёрной.

Изменение толщины линий

Теперь плавно перейдём от изменения цветов к изменению значения толщины линий. Для данного функционала существует ещё один метод из JavaScript API — lineWidth.

Можете добавить данный код в прошлый пример:

И вот какой у вас получится результат:

Такой же принцип вы можете применить со схемами. К примеру, вы можете изменить пример с треугольником:

И вот что у вас получится:

Также в JavaScript API, существует ещё метод, который позволят вам изменить вид линий. К примеру, lineCap изменяет вид отображения конца линии, а lineJoin изменят отображение углов. Более подробную информацию вы можете найти в спецификации.

Стираем объекты из Canvas

Последняя вещь, которую я хочу вам сегодня показать – это стирание объектов. Вы уже знаете, как нарисовать фигуру. Теперь пришло время узнать как от неё избавиться :)

В принципе тут всё так же просто; вам нужно всего-навсего воспользоваться очередным методом из JavaScript API. Этот метод называется clearRect. Его задача заключается в том, чтобы сделать каждый указанный пиксель полностью прозрачным.

В этом примере на canvas 500px в ширину и 500px в высоту. Для очищения всей площади, вам необходимо сделать следующее:

В этом примере скорее всего не нужно подтверждать работу кода скриншотом, так как вы ничего не увидите. Квадрат действительно был нарисован, а затем мгновенно стёрт.

Заметьте: аргументы для метода clearRect точно такие же, как и для fillRect; x, y, ширина и высота.

Если вы не определились с высотой и шириной, то можете писать и так:

Стирание небольших фрагментов

Для того чтобы стереть небольшой фрагмент, вам не обязательно зачищать всю площадь элемента canvas. Вы без проблем можете стереть необходимую вам область. Представьте, что у вас нарисовано 2 квадрата, один из которых вы хотите стереть:

На данный момент картина такая:

Вы без проблем можете стереть черный квадрат, а красный оставить на месте при помощи метода clearRect:

Заметьте, что данные должны совпадать с теми, что вы указывали при создании элемента. На самом деле данный метод просто изменяет прозрачность каждого пискеля:

Довольно-таки просто, не так ли? Вы нечасто будете стирать элементы при рисовании, однако эти знания понадобятся вам, когда мы будем учиться делать анимацию.

Идём в ногу со временем

Canvas прост в использовании и изучении

Надеюсь, вы убедились в том, что canvas — это очень перспективный элемент веб страницы. Он позволяет создавать вам изображения, используя чистый код без никаких плагинов. Он прост в использовании и изучении, и на самом деле в умелых руках может превратиться во что-то очень оригинальное.

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

А сейчас, я надеюсь, вы получили много полезной информации, которая позволит вам получить общее представление об canvas. Данный элемент — это фантастическая технология, которая позволит вам реализовать все фантазии, которые хранятся у вас в голове.

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.net.tutsplus.com/tutorials/javascript-ajax/canvas-from-scratch-introducing-canvas/
Перевел: Станислав Протасевич
Урок создан: 28 Марта 2011
Просмотров: 59867
Правила перепечатки

5 последних уроков рубрики «HTML и DHTML»

Лайфхак: наиполезнейшая функция var_export()

При написании или отладки PHP скриптов мы частенько пользуемся функциями var_dump() и print_r() для вывода предварительных данных массив и объектов. В этом посте я бы хотел рассказать вам о функции var_export(), которая может преобразовать массив в формат, пригодный для PHP кода.

17 бесплатных шаблонов админок

Парочка бесплатных шаблонов панелей администрирования.

30 сайтов для скачки бесплатных шаблонов почтовых писем

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

Как осуществить задержку при нажатии клавиши с помощью jQuery?

К примеру у вас есть поле поиска, которое обрабатывается при каждом нажатии клавиши клавиатуры. Если кто-то захочет написать слово Windows, AJAX запрос будет отправлен по следующим фрагментам: W, Wi, Win, Wind, Windo, Window, Windows. Проблема?.

15 новых сайтов для скачивания бесплатных фото

Подборка из 15 новых сайтов, где можно скачать бесплатные фотографии для заполнения своих сайтов.

Глубокое погружение в Canvas

We recommend upgrading to the latest Google Chrome or Firefox.

Join GitHub today

GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.

Learning / JavaScript.md

Онлайн-учебники

Видеоуроки

Статьи

Ссылки

Онлайн-учебники

Видеоуроки

Статьи

  • © 2020 GitHub , Inc.
  • Terms
  • Privacy
  • Security
  • Status
  • Help

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Глубокое обучение. Погружение в мир нейронных сетей PDF

Перед вами – первая книга о глубоком обучении, написанная на русском языке. Глубокие модели оказались ключом, который подходит ко всем замкам сразу: новые архитектуры и алгоритмы обучения, а также увеличившиеся вычислительные мощности и появившиеся огромные наборы данных привели к революционным прорывам в компьютерном зрении, распознавании речи, обработке естественного языка и многих других типично «человеческих» задачах машинного обучения. Эти захватывающие идеи, вся история и основные компоненты революции глубокого обучения, а также самые современные достижения этой области доступно и интересно изложены в книге. Максимум объяснений, минимум кода, серьезный материал о машинном обучении и увлекательное изложение – в этой уникальной работе замечательных российских ученых и интеллектуалов.

Великолепная книга, просто великолепная! Главным её достоинством является то, что хотя она рассказывает о очень серьёзных вещах (машинное обучение, нейронные сети и т.д.) написана очень простым, понятным и доступным языком. Изложение очень живое, приводится масса интересных примеров и около-научных рассуждений, некоторые из них весьма нетривиальны. В общем всем, кто интересуется современными подходами в машинном обучении (полностью согласен с авторами, что термин «искусственный интеллект» на русском языке прсто режет слух -:) рекомендую прочесть и изучить эту книгу с большим вниманием!

Рисование фигур с помощью canvas

Теперь, установив наше окружение canvas, мы можем погрузиться в детали того, как рисовать в canvas. К концу этой статьи, Вы научитесь рисовать прямоугольники, треугольники, линии, дуги и кривые, при условии что Вы хорошо знакомы с основными геометрическими фигурами. Работа с путями весьма важна, когда рисуете объекты на canvas и мы увидим как это может быть сделано.

Сетка

Перед тем, как мы начнем рисовать, нам нужно поговорить о сетке canvas или координатной плоскости. Наш HTML каркас из предыдущей страницы включал в себя элемент canvas 150 пикселей в ширину и 150 пикселей в высоту. Справа можно увидеть этот canvas с сеткой , накладываемой по умолчанию . Обычно 1 единица на сетке соответствует 1 пикселю на canvas. Начало координат этой сетки расположено в верхнем левом углу в координате ( 0,0 ) . Все элементы размещены относительно этого начала . Так им образом, положение верхнего левого угла синего квадрата составляет х пикселей слева и у пикселей сверху, на координате , у) . Позже в этом уроке мы увидим, как можно перевести начало координат в другое место , вращать сетку и даже масштабировать ее , но сейчас мы будем придерживаться настроек сетки по умолчанию.

Рисование прямоугольников


Сначала рассмотрим прямоугольник. Ниже представлены три функции рисования прямоугольников в canvas:

fillRect(x, y, width, height) Рисование заполненного прямоугольника. strokeRect(x, y, width, height) Рисование прямоугольного контура. clearRect(x, y, width, height) Очистка прямоугольной области, делая содержимое совершенно прозрачным.

Каждая из приведенных функций принимает несколько параметров:

  • x, y устанавливают положение верхнего левого угла прямоугольника в canvas (относительно начала координат);
  • width (ширина) и height (высота) определяют размеры прямоугольника.

Ниже приведена функция draw(), использующая эти три функции.

Пример создания прямоугольных фигур

Этот пример изображен ниже.

Screenshot Live sample

Функция fillRect() рисует большой чёрный квадрат со стороной 100 px. Функция clearRect() вырезает квадрат 60х60 из центра, а функция strokeRect() создает прямоугольный контур 50х50 пикселей внутри очищенного квадрата.

На следующей странице мы рассмотрим две альтернативы методу clearRect(), и также увидим, как можно изменять цвет и стиль контура отображаемых фигур.

В отличие от функций создания контуров, которые будут рассмотрены в следующем разделе, все три функции создания прямоугольника сразу же отображаются на canvas.

Рисование контуров (path)

Остальные примитивные фигуры создаются контурами. Контур — это набор точек, которые, соединяясь в отрезки линий, могут образовывать различные фигуры, изогнутые или нет, разной ширины и разного цвета. Контур (или субконтур) может быть закрытым.

Создание фигур используя контуры происходит в несколько важных шагов:

  1. Сначала вы создаете контур.
  2. Затем, используя команды рисования, рисуете контур.
  3. Потом закрываете контур.
  4. Созданный контур вы можете обвести или залить для его отображения.

Здесь приведены функции, которые можно использовать в описанных шагах:

beginPath() Создает новый контур. После создания используется в дальнейшем командами рисования при построении контуров. Path методы Методы для установки различных контуров объекта. closePath() Закрывает контур , так что будущие команды рисования вновь направлены контекст . stroke() Рисует фигуру с внешней обводкой. fill() Рисует фигуру с заливкой внутренней области.

Первый шаг создания контура заключается в вызове функции beginPath() . Внутри содержатся контуры в виде набора суб-контуров (линии, дуги и др.), которые вместе образуют форму фигуры. Каждый вызов этого метода очищает набор, и мы можем начинать рисовать новые фигуры.

Вторым шагом является вызов методов, определяемых видом контура, который нужно нарисовать. Их мы рассмотрим позднее.

Третий и необязательный шаг — это вызов closePath() . Этот метод пытается закрыть фигуру, рисуя прямую линию из текущей точки в начальную. Если фигура была уже закрыта или является просто точкой, то функция ничего не делает.

Рисование треугольника

Например, код для рисования треугольника будет выглядеть как-то так:

Результат выглядит так:

Screenshot Live sample

Передвижение пера

Одна очень полезная функция, которая ничего не рисует, но связана по смыслу с вышеописанными функциями — это moveTo() . Вы можете представить это как отрыв (подъем) пера от бумаги и его перемещение в другое место.

moveTo(x, y) Перемещает перо в точку с координатами x и y.

При инициализации canvas или при вызове beginPath() , вы захотите использовать функцию moveTo() для перемещения в точку начала рисования. Можно использовать moveTo() и для рисования несвязанного(незакрытого) контура. Посмотрите на смайлик ниже.

Вы можете проверить это сами, используя участок кода ниже. Просто вставьте в функцию draw() , рассмотренную ранее.

Результат этого ниже:

Screenshot Live sample

Если вы захотите увидеть соединные линии, то можете удалить вызов moveTo() .

Note: Подробнее о функции arc() ,посмотрите Дуги .

Линии

Для рисования прямых линий используйте метод lineTo() .

lineTo(x, y) Рисует линию с текущей позиции до позиции, определенной x и y .

Этот метод принимает два аргумента x и y , которые являются координатами конечной точки линии . Начальная точка зависит от ранее нарисованных путей, причём конечная точка предыдущего пути является начальной точкой следующего и т. д. Начальная точка также может быть изменена с помощью метода moveTo() .

Пример ниже рисует два треугольника, один закрашенный и другой обведен контуром.

Отрисовка начинается с вызова beginPath() , чтобы начать рисовать путь новой фигуры . Затем мы используем метод moveTo() , чтобы переместить начальную точку в нужное положение . Ниже рисуются две линии , которые образуют две стороны треугольника .

Screenshot Live sample

Вы заметите разницу между закрашенным и обведенным контуром треугольниками. Это, как упоминалось выше , из-за того, что фигуры автоматически закрываются , когда путь заполнен (т. е. закрашен) , но не тогда, когда он очерчен (т. е. обведен контуром) . Если бы мы не учли closePath() для очерченного треугольника , тогда только две линии были бы нарисованы, а не весь треугольник .

Для рисования дуг и окружностей, используем методы arc() и arcTo().

arc(x, y, radius, startAngle, endAngle, anticlockwise) Рисуем дугу с центром в точке (x,y) радиусом r , начиная с угла startAngle и заканчивая в endAngle в направлении против часовой стрелки anticlockwise (по умолчанию по ходу движения часовой стрелки). arcTo(x1, y1, x2, y2, radius) Рисуем дугу с заданными контрольными точками и радиусом, соединяя эти точки прямой линией.

Рассмотрим детальнее метод arc(), который имеет пять параметров: x и y — это координаты центра окружности, в которой должна быть нарисована дуга. radius — не требует пояснений. Углы startAngle и endAngle определяют начальную и конечную точки дуги в радианах вдоль кривой окружности. Отсчет происходит от оси x. Параметр anticlockwise — логическое значение, которое, если true , то рисование дуги совершается против хода часовой стрелки; иначе рисование происходит по ходу часовой стрелки.

Note: Углы в функции arc() измеряют в радианах, не в градусах. Для перевода градусов в радианы вы можете использовать JavaScript-выражение: radians = (Math.PI/180)*degrees .

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

Два for цикла размещают дуги по столбцам и строкам. Для каждой дуги, мы начинаем новый контур, вызывая beginPath() . В этом коде каждый параметр дуги для большей ясности задан в виде переменной, но вам не обязательно делать так в реальных проектах.

Координаты x и y должны быть достаточно ясны. radius and startAngle — фиксированы. endAngle начинается со 180 градусов (полуокружность) в первой колонке и, увеличиваясь с шагом 90 градусов, достигает кульминации полноценной окружностью в последнем столбце.

Установка параметра clockwise определяет результат; в первой и третьей строках рисование дуг происходит по часовой стрелке, а во второй и четвертой — против часовой стрелки. Благодаря if-условию верхняя половина дуг образуется с контуром, (обводкой), а нижняя половина дуг — с заливкой.

Note: Этот пример требует немного большего холста (canvas), чем другие на этой странице: 150 x 200 pixels.

Screenshot Live sample

Безье и квадратичные кривые

Следующим типом доступных контуров являются кривые Безье, и к тому же доступны в кубическом и квадратичном вариантах. Обычно они используются при рисовании сложных составных фигур.

quadraticCurveTo(cp1x, cp1y, x, y) Рисуется квадратичная кривая Безье с текущей позиции пера в конечную точку с координатами x и y , используя контрольную точку с координатами cp1x и cp1y . bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) Рисуется кубическая кривая Безье с текущей позиции пера в конечную точку с координатами x и y , используя две контрольные точки с координатами ( cp1x , cp1y ) и (cp2x, cp2y).

Различие между ними можно увидеть на рисунке, изображенном справа. Квадратичная кривая Безье имеет стартовую и конечную точки (синие точки) и всего одну контрольную точку (красная точка), в то время как кубическая кривая Безье использует две контрольные точки.

Параметры x и y в этих двух методах являются координатами конечной точки. cp1x и cp1y — координаты первой контрольной точки, а cp2x и cp2y — координаты второй контрольной точки.

Использование квадратичных или кубических кривых Безье может быть спорным выходом, так как в отличие от приложений векторной графики типа Adobe Illustrator, мы не имеем полной видимой обратной связи с тем, что мы делаем. Этот факт делает довольно сложным процесс рисования сложных фигур. В следующем примере мы нарисуем совсем простую составную фигуру, но, если у вас есть время и ещё больше терпения, можно создать более сложные составные фигуры.

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

Квадратичные кривые Безье

В этом примере многократно используются квадратичные кривые Безье для рисования речевой выноски.

Screenshot Live sample

Кубические кривые Безье

В этом примере нарисовано сердце с использованием кубических кривых Безье.

Screenshot Live sample

Прямоугольники

Все эти методы мы видели в Рисование прямоугольников, которые рисуют прямоугольники сразу в canvas, так же есть метод rect() , который не отображает, а только добавляет контур рисования (path) заданного прямоугольника к последнему открытому контуру.

rect(x, y, width, height)
Добавляет в path прямоугольник, верхний левый угол которого указан с помощью (x, y) с вашими width и height

Когда этот метод вызван, автоматически вызывается метод moveTo() с параметрами (x, y). Другими словами, позиция курсора устанавливается в начало добавленного прямоугольника.

Создание комбинаций

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

Конечное изображение выглядит так:

Screenshot Live sample

Мы не будем подробно останавливаться на том, так как это на самом деле удивительно просто. Наиболее важные вещи, которые следует отметить, это использование свойства fillStyle в контексте рисования и использование функции утилиты (в данном случае roundedRect() ). Использование функций утилиты для битов чертежа часто может быть очень полезным и сократить количество необходимого кода, а также его сложность.

Позже, в этом уроке, мы еще раз рассмотрим fillStyle , но более подробно. Здесь же мы используем его для изменения цвета заливки путей вместо цвета по умолчанию от черного до белого, а затем обратно.

Path2D объекты


Как мы видели в последнем примере, есть серия путей и команд для рисования объектов на вашем холсте. Чтобы упростить код и повысить производительность, объект Path2D , доступный в последних версиях браузеров, позволяет вам кэшировать или записывать эти команды рисования. Вы можете быстро запускать свои пути.
Давайте посмотрим, как мы можем построить объект Path2D :

Path2D() Конструктор Path2D() возвращает вновь созданный объект Path2D необязательно с другим путем в качестве аргумента (создает копию) или необязательно со строкой, состоящей из данных пути SVG path .

Все методы path , такие как moveTo , rect , arc , или quadraticCurveTo , итп, которые мы уже знаем, доступны для объектов Path2D

API Path2D также добавляет способ комбинирования путей с использованием метода addPath . Это может быть полезно, если вы хотите, например, создавать объекты из нескольких компонентов.

Path2D.addPath(path [, transform]) Добавляет путь к текущему пути с необязательной матрицей преобразования.

Path2D пример

В этом примере мы создаем прямоугольник и круг. Оба они сохраняются как объект Path2D , поэтому они доступны для последующего использования. С новым API Path2D несколько методов были обновлены, чтобы при необходимости принять объект Path2D для использования вместо текущего пути. Здесь stroke и fill используются с аргументом пути, например, для рисования обоих объектов на холст.

Screenshot Live sample

Использование SVG путей

Еще одна мощная функция нового Canvas Path2D API использует данные пути SVG, SVG path data, для инициализации путей на вашем холсте. Это может позволить вам передавать данные пути и повторно использовать их как в SVG, так и в холсте.

Путь перемещается в точку ( M10 10 ), а затем горизонтально перемещается на 80 пунктов вправо ( h 80 ), затем на 80 пунктов вниз ( v 80 ), затем на 80 пунктов влево ( h -80 ), а затем обратно на start ( z ).
Этот пример можно увидеть на странице Path2D constructor.

Элемент Canvas

Самым важным новым инструментом для расширенных приложений HTML5 является — поверхность для рисования, на которой пользователь может дать волю своим непризнанным художественным способностям. Холст стоит обособленно от всех других элементов HTML, т.к. для работы с ним требуется JavaScript. Иного способа для черчения фигур или рисования изображений попросту нет. Это означает, что холст, по сути, является средством программирования, таким, которое позволяет выйти далеко за пределы первоначального концепта Интернета, согласно которому он основывается на содержимом документного типа.

С первого взгляда использование холста может казаться похожим на использование программы MS Paint, вставленной в окно браузера. Но, копнув поглубже, можно увидеть, что холст — ключевой компонент для ряда графически продвинутых приложений, включая некоторые приложения, о которых вы уже, наверное, и сами подумали — игры, картографические инструменты и динамические графики, и такие, которые вы, возможно, не могли вообразить — музыкально-световые представления и эмуляторы физических процессов.

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

Базовые возможности Canvas

Элемент предоставляет рабочее пространство для рисования. С точки зрения разметки, это простой до предела элемент с тремя атрибутами — id, width и height:

Атрибут id присваивает данному холсту однозначное имя, требуемое для его идентификации кодом JavaScript А атрибуты width и height устанавливают ширину и высоту холста в пикселах, соответственно.

Размеры холста всегда следует устанавливать посредством атрибутов width и height элемента , а не с помощью свойств width и height таблицы стилей. В противном случае возможно возникновение проблемы с искажением рисунков.

Обычно холст отображается как пустой прямоугольник без рамки, т.е. он не виден вообще. Чтобы сделать холст видимым, с помощью таблицы стилей ему можно дать цветной фон или рамку, как показано в следующем коде:

Полученный результат, который будет нашей отправной точкой в изучении Canvas показан на рисунке:

Чтобы рисовать на холсте, нужно написать определенный объем кода JavaScript. Эта задача состоит из двух этапов. Первым делом наш сценарий должен получить объект холста, для чего используется метод document.getElementById. Затем надо получить двумерный контекст рисования, для чего применяется метод getContext():

Контекст можно рассматривать как сверхмощный инструмент рисования, который выполняет все необходимые для этого операции, такие как создание прямоугольников, печатание текста, вставка изображений и т.п. Это что-то наподобие универсальной мастерской для операций рисования на холсте.

Тот факт, что контекст явно называется двумерным (и в коде указывается как «2d»), порождает очевидный вопрос, а именно: существует ли трехмерный контекст рисования? Ответ на этот вопрос — пока нет, но ясно, что создатели HTML5 оставили место для него в будущем.

Получить объект контекста и начать рисование можно в любой момент, например, сразу же после загрузки страницы, когда пользователь щелкнет мышью, и т.п. Вам, скорее всего, уже не терпится создать страницу, на которой можно было бы сразу же приступить к практической работе с холстом. В следующем листинге приведен код для создания шаблона такой страницы:

В разделе разметки для холста создается рамка, указывающая его местонахождение на странице. А в разделе

Вершины фигур, создаваемые соединяющимися линиями, можно оформить тремя разными способами, присваивая свойству контекста lineJoin соответствующие значения. Значение round округляет вершины, значение mitre соединяет линии в вершине «под ус», а значение bevel обрезает вершины прямой линией. По умолчанию свойству lineJoin присвоено значение mitre.

В большинстве случаев, чтобы создать сложную фигуру, ее очертания нужно создавать пошагово, по одному отрезку за раз. Но одна фигура является достаточно важной, и для нее выделен отдельный метод. Это прямоугольник. Заполнить прямоугольную область заливкой можно за один шаг методом fillRect(), которому в параметрах передаются координаты левого верхнего угла, ширина и высота прямоугольника. В один присест, используя метод strokeRect(), также можно нарисовать и очертания прямоугольника.

Цвет заливки для метода fillRect() устанавливается так же, как и для метода fill() свойством fillStyle. Толщина и цвет линий прямоугольника определяются текущими значениями свойств lineWidth и strokeStyle, точно так же, как для метода stroke().

Например, следующий код заполняет заливкой прямоугольную область размером 100×200 пикселов с левым верхним углом в точке (100, 40):

Кривые линии

Чтобы рисовать что-то более сложное, чем линии и прямоугольники, нужно изучить следующие четыре метода: arc(), arcTo(), bezierCurveTo() и quadraticCurveTo(). Все эти методы рисуют кривые линии, и хотя каждый делает это по-своему, все они требуют хотя бы небольших (а некоторые и больших) знаний математики.

Изо всех этих методов самый простой — метод arc(), который рисует дугу. Чтобы нарисовать дугу, нужно сначала представить себе в уме полный круг, а потом решить, какую часть его окружности вы хотите рисовать:

Дуга выглядит достаточно простой фигурой, но чтобы полностью ее описать, требуется несколько единиц информации. Сначала нужно нарисовать воображаемый круг. Для этого надо знать координаты центра (1) и радиуса (2), который определяет размер круга. Далее следует описать длину дуги на окружности, для чего требуется угол начала дуги (3) и угол ее окончания (4). Значения углов должны быть в радианах, которые выражаются через число π. Угол всей окружности равен 2π, половины — 1π и т.д.

Собрав все необходимые данные, передаем их методу arc():

Дугу можно закрыть, соединив ее концы прямой линией. Для этого нужно вызвать метод closePath() перед тем, как вызывать метод stroke(). Кстати, окружность — это та же дуга, просто с углом 2π. Рисуется окружность следующим образом:

Метод arc() нельзя применять для рисования овала (вытянутого круга). Для этого нужно использовать либо более сложные методы для рисования кривых, либо применить трансформации.

Три других метода рисования кривых — arcTo(), bezierCurveTo() и quadraticCurveTo() — могут быть несколько посложнее для тех, кто не в ладах с геометрией. Они основаны на принципе контрольных точек, т.е. точек, которые сами не являются частью кривой, но управляют ее формой. Наиболее известным типом таких кривых являются кривые Безье, которые используются практически в каждой программе рисования. Причиной популярности этого метода является, его способность создавать плавные кривые, независимо от их размера.

Кривая Безье создается следующим кодом:

Контур сложной фигуры часто состоит из ряда дуг и кривых, соединяющихся друг с другом. По окончанию рисования всех составляющих можно вызвать метод closePath(), чтобы обвести или закрасить всю фигуру. Чтобы побольше узнать о кривых Безье, лучше поэкспериментировать с ними, а хорошую игровую площадку для этого можно найти на этой странице: Canvas Bézier Curve Example.

Рисование на холсте для тех, кто ненавидит математику

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

Использовать библиотеку рисования

Зачем набивать себе шишки на лбу, если можно использовать готовую библиотеку для рисования кругов, треугольников, овалов и многоугольников за один прием? Идея простая — вызывается метод высшего уровня (скажем, fillEllipse(), которому передаются соответствующие координаты), и библиотека JavaScript преобразует все это в требуемую операцию на холсте. В качестве двух хороших примеров такой библиотеки можно назвать CanvasPlus и Artisan JS. Но эти, и другие, библиотеки продолжают развиваться, поэтому еще рано говорить, какие из них выживут и окажутся пригодными для профессионального применения.

Рисовать растровые изображения

Вместо того чтобы кропотливо рисовать каждую требуемую фигуру самому, можно скопировать в холст уже готовую графику. Например, изображение круга, сохраненное в файле формата PNG, можно вставить в холст. Но этот подход не позволит использовать гибкость при манипулировании изображением, например растягивать его, перемещать или удалять его части и т.п.

Использовать профессиональный инструмент

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

В этом отношении представляет интерес одно из таких средств — модуль Ai->Canvas для Adobe Illustrator. Данный модуль преобразует созданную в Adobe Illustrator графику в страницу HTML с кодом JavaScript, который воспроизводит эту графику на холсте.

как проходит монтаж

80%
прочности
через 24 часа

1-2 часа
время
затвердевания

Монтаж бетонного полотна Concrete Canvas: быстро, удобно, экономично

В зависимости от формы поставки полотна его разворачивание производится вручную или с помощью траверсы, закрепленной на подъемном кране или ковше экскаватора.

Главное требование при укладке — чтобы отдельные полотна шли внахлест, то есть чтобы край предыдущего куска полотна перекрывал край следующего. Это необходимо для их последующего скрепления между собой.

Полотно легко отрезается от рулона с помощью обычного ручного инструмента

Для крепления бетонного холста на поверхности (например на грунте) подходят обычные анкера или стальные колья со шляпками.

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

Между собой отдельные полотна (куски) Concrete Canvas можно крепить различными способами: болтами, саморезами, клеем-герметиком, строительным раствором. Эти способы могут применяться как в комплексе, так и по отдельности. Все зависит от задачи, которую необходимо решить с помощью бетонного полотна. Например, если требуется укрепить канаву, то клей обеспечит герметичность стыков, а саморезы — дополнительную прочность крепления. Если требуется укрепить пологий склон, то, возможно, достаточно будет саморезов.

Смачивание производится путем разбрызгивания воды (не под давлением!) по поверхности холста или путем его погружения в воду. Подходит как пресная, так и морская вода.

Разбрызгивать воду следует до тех пор, пока полотно не будет оставаться ощутимо влажным даже спустя несколько минут после прекращения смачивания. Опасаться чрезмерного смачивания не стоит. Даже если монтаж Concrete Canvas будет проходить под проливным дождем, это никак не скажется на его конечных характеристиках.

Concrete Canvas застывает в течение 1—2 часов в зависимости от температуры окружающей среды. На протяжении этого времени с ним можно продолжать работать. Если все работы уже закончены, то объект можно покинуть. Окончательно полотно застынет через 24 часа.

Глубокое погружение в систему рендеринга WPF

На перевод этой статьи меня подтолкнуло обсуждение записей «Почему WPF живее всех живых?» и «Семь лет WPF: что изменилось?» Исходная статья написана в 2011 году, когда Silverlight еще был жив, но информация по WPF не потеряла актуальности.

Сначала я не хотел публиковать эту статью. Мне казалось, что это невежливо — о мертвых надо говорить либо хорошо, либо ничего. Но несколько бесед с людьми, чье мнение я очень ценю, заставили меня передумать. Вложившие много усилий в платформу Microsoft разработчики должны знать о внутренних особенностях ее работы, чтобы, зайдя в тупик, они могли понимать причины произошедшего и более точно формулировать пожелания к разработчикам платформы. Я считаю WPF и Silverlight хорошими технологиями, но… Если вы следили за моим Twitter последние несколько месяцев, то некоторые высказывания могли показаться вам безосновательными нападками на производительность WPF и Silverlight. Почему я это писал? Ведь, в конце концов, я вложил тысячи и тысячи часов моего собственного времени в течение многих лет, пропагандируя платформу, разрабатывая библиотеки, помогая участникам сообщества и так далее. Я однозначно лично заинтересован. Я хочу, чтобы платформа стала лучше.

Производительность, производительность, производительность

При разработке, затягивающего, ориентированного на потребителя, пользовательского интерфейса, производительность для вас важнее всего. Без нее все остальное не имеет смысла. Сколько раз вам приходилось упрощать интерфейс, потому что он лагал? Сколько раз вы придумывали «новую, революционную модель пользовательского интерфейса», которую приходилось выкинуть на помойку, так как имеющаяся технология не позволяла ее реализовать? Сколько раз вы говорили клиентам, что для полноценной работы нужен четырехядерный процессор с частотой 2,4 ГГц? Клиенты неоднократно спрашивали меня, почему на WPF и Sliverlight они не могут получить такой же плавный интерфейс, как в приложении для iPad, даже имея вчетверо более мощный PC. Эти технологии может и подходят для бизнес-приложений, но они явно не подходят для пользовательских приложений следующего поколения.

Но ведь WPF использует аппаратное ускорение. Почему же вы считаете его неэффективным?

WPF действительно использует аппаратное ускорение и некоторые моменты его внутренней реализации сделаны очень неплохо. К сожалению, эффективность использования GPU намного ниже, чем могла бы быть. Система рендеринга WPF использует очень грубую силу. Я надеюсь объяснить это утверждение чуть ниже.

Анализируем единичный проход рендеринга WPF

Для анализа производительности нам надо понять, что на самом деле происходит внутри WPF. Для этого я использовал PIX, профайлер Direct3D, поставляемый вместе с DirectX SDK. PIX запускает ваше D3D-приложение и внедряет ряд перехватчиков во все вызовы Direct3D для их анализа и мониторинга.

Я создал простое WPF-приложение, в котором слева направо выводятся два эллипса. Оба эллипса одного цвета (#55F4F4F5) с черным контуром.

И как WPF рендерит это?

Прежде всего WPF очищает (#ff000000) грязную область, которую он собирается перерисовать. Грязные области нужны для сокращения числа пикселей, посылаемых на финальную стадию слияния (output merger stage) в конвейере GPU. Мы даже может предположить, что это сокращает объем геометрии, которую придется перетесселировать (be re-tessellated), подробнее об этом чуть позже. После очистки грязной области наш кадр выглядит вот так

После этого WPF делает что-то непонятное. Сначала он заполняет вершинный буфер (vertex buffer), после чего рисует что-то, выглядящее как прямоугольник поверх грязной области. Теперь кадр выглядит вот так (захватывающе, не правда ли?):

После этого он тесселирует эллипс на GPU. Тесселяция, как вы уже возможно знаете — это превращение геометрии нашего 100х100 эллипса в набор треугольников. Делается это по следующим причинам: 1) треугольники являются естественной единицей рендеринга для GPU 2) тесселяция эллипса может вылится всего в несколько сотен треугольников, что намного быстрее растеризации 10 000 пикселов с антиалиасингом средствами CPU (что делает Silverlight). На скриншоте ниже видно, как выглядит тесселяция. Знакомые с 3D графикой читатели могли заметить, что это треугольные полосы (triangle strip). Обратите внимание, что в тесселяции эллипс выглядит незавершенным. В качестве следующего шага WPF берет тесселяцию, загружает ее в вершинный буфер GPU и делает еще один вызов отрисовки (draw call) с использованием пиксельного шейдера, который настроен для использования «кисти» настроенной в XAML.

Помните, что я отметил незавершенность эллипса? Это действительно так. WPF генерирует то, что программисты Direct3D знают как «набор линий» (line list). GPU понимает линии так же хорошо, как и треугольники. WPF заполняет вершинный буфер этими линиями и догадайтесь что? Правильно, выполняет еще один вызов отрисовки (draw call)? Набор линий выглядит вот так:


Теперь-то WPF закончил рисовать эллипс, не так ли? Нет! Вы забыли о контуре! Контур тоже является набором линий. Его тоже посылают в вершинный буфер и выполняют еще один вызов отрисовки. Контур выглядит вот так

К этому моменту мы нарисовали один эллипс, так что наш кадр выглядит вот так:

Всю процедуру необходимо повторить для каждого эллипса на сцене. В нашем случае два раза.

Я не понял. Почему это плохо для производительности?

Первое, что вы могли заметить — для рендеринга одного эллипса нам потребовались три вызова отрисовки и два обращения к вершинному буферу. Чтобы объяснить неэффективность этого подхода мне придется немного рассказать о работе GPU. Для начала, современные GPU работают ОЧЕНЬ БЫСТРО и асинхронно с GPU. Но при некоторых операциях происходят дорогостоящие переключения из пользовательского режима в режим ядра (user-mode to kernel mode transitions). При заполнении вершинного буфера он должен быть заблокирован. Если буфер в этот момент используется GPU, это вынуждает GPU синхронизироваться с CPU и резко снижает производительность. Вершинный буфер создается с D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, но когда он блокируется (что случается нередко), D3DLOCK_DISCARD не используется. Это может вызвать потерю скорости (синхронизацию GPU и CPU) в GPU, если буфер уже используется GPU. В случае большого количества вызовов отрисовки у нас есть высокая вероятность получить множество переходов в режим ядра и большую нагрузку в драйверах. Для повышения производительности нам надо послать на GPU настолько много работы, насколько возможно, иначе ваш CPU будет занят, а GPU будет простаивать. Не забывайте, что в этом примере речь шла только об одном кадре. Типичный интерфейс на WPF пытается выводить 60 кадров в секунду! Если вы когда-либо пытались выяснить, отчего ваш поток рендеринга так сильно загружает процессор, то скорее всего обнаруживали, что большая часть нагрузки идет от вашего драйвера GPU.

А что с кэшированным построением (Cached Composition)? Оно ведь повышает производительность!

Вне всяких сомнений, повышает. Кэшированное построение или BitmapCache кэширует обьекты в текстуру GPU. Это означает, что вашему CPU не надо перетесселировать, а GPU не надо перерастрировать (re-rasterize). При выполнении одного прохода рендеринга WPF просто использует текстуру из видеопамяти, увеличивая производительность. Вот BitmapCache эллипса:

Но у WPF есть темные стороны и в этом случае. Для каждого BitmapCache он выполняет отдельный вызов отрисовки. Не буду врать, иногда вам действительно надо выполнять вызов отрисовки для рендеринга единичного объекта (visual). Всякое бывает. Но давайте представим себе сценарий, в котором у нас есть с 300 анимированными BitmapCached-эллипсами. Продвинутая система поймет, что ей надо отрендерить 300 текстур и все они z-упорядочены (z-ordered) одна за другой. После этого она соберет их пакеты максимального размера, насколько я помню, DX9 может принимать до 16 входящих элементов (sampler inputs) за раз. В этом случае мы получим 16 вызовов отрисовки вместо 300, что заметно снизит нагрузку на CPU. В терминах 60 кадров в секунду мы снизим нагрузку с 18 000 вызовов отрисовки в секунду до 1125. В Direct 3D 10 количество входящих элементов намного выше.

Ладно, я дочитал до этого места. Расскажите мне, как WPF использует пиксельные шейдеры!

У WPF есть расширяемый API пиксельных шейдеров и некоторые встроенные эффекты. Это позволяет разработчикам добавлять по-настоящему уникальные эффекты в их пользовательский интерфейс. При примернии шейдера к существующей текстуре в Direct 3D обычно используется промежуточная цель отрисовки (intermediate rendertarget)… и конце концов вы не можете использовать в качестве образца (sample from) текстуру, в которую пишете! WPF тоже делает это, но, к несчастью, он создает полностью новую текстуру КАЖДЫЙ КАДР и уничтожает ее по завершении. Создание и уничтожение ресурсов GPU — это одна из самых медленных вещей, которые только можно делать при обработке каждого кадра. Я обычно не поступаю так даже с выделением системной памяти схожего объема. При повторном использовании этих промежуточных поверхностей можно было бы достигнуть очень значительного повышения производительности. Если вы когда-либо задавались вопросом, почему ваши аппаратно-ускоренные шейдеры создают заметную нагрузку на CPU, то теперь знаете ответ.

Но может быть именно так и надо рендерить векторную графику на GPU?

Microsoft приложила немало усилий для исправлений этих проблем, к несчастью это было сделано не в WPF, а в Direct 2D. Посмотрите на эту группу из 9 эллипсов, отрендеренных Direct2D:

Помните, как много вызовов отрисовки требовалось WPF для рендеринга одного эллипса с контуром? А блокировок вершинного буфера? Direct2D делает это за ОДИН вызов отрисовки. Тесселяция выглядит вот так

Direct 2D старается нарисовать как можно больше за один раз, максимизируя использование GPU и минимизируя загрузку CPU. Прочитайте Insights: Direct2D Rendering в конце вот этой страницы, там Марк Лавренс (Mark Lawrence) объясняет многие внутренние детали работы Direct 2D. Вы можете заметить, что несмотря на всю скорость Direct 2D есть еще больше областей, где она будет улучшена во второй версии. Вполне возможно, что версия 2 Direct 2D будет использовать аппаратное ускорение тесселяции DX11.

Глядя на API Direct 2D вполне можно предположить, что значительная часть кода была взята из WPF. Посмотрите это старое видео про Avalon, в нем Майкл Воллент (Michael Wallent) рассказывает о разработке замены GDI на основе этой технологии. У него очень похожий геометрический API и терминология. Внутри он похожий, но очень оптимизированный и современный.

А что с Silverlight?

Я мог бы заняться Silverlight, но это будет излишним. Производительность рендеринга в Silverlight тоже низкая, но причины иные. Он использует для отрисовки CPU (даже для шейдеров, насколько я помню, они частично написаны на ассемблере), но CPU как минимум в 10-30 раз медленнее GPU. Это оставляем вам гораздо меньше процессорной мощности для рендеринга пользовательского интерфейса и еще меньше для логики вашего приложения. Его аппаратное ускорение очень слабо развито и почти в точности повторяет кэшированное построение WPF и ведет себя аналогичным образом, осуществляя вызов отрисовки для каждого объекта с BitmapCache (BitmapCached visual).

И что же нам теперь делать?

Этот вопрос очень часто задают мне клиенты, столкнувшиеся с проблемами WPF и Silverlight. К несчастью, у меня нет однозначного ответа. Те кто могут, делают собственные фреймворки, заточенные под свои специфические потребности. Остальным приходится смириться, так как альтернатив WPF и SL в их нишах нет. Если мои клиенты просто разрабатывают бизнес-приложения, то у них не так много проблем с скоростью и они просто наслаждаются производительностью работы программистов. Настоящие проблемы у тех, кто хочет строить действительно интересные интерфейсы (то есть приложения для потребителей или киосков (consumer apps or kiosk apps)).

HTML5 Rocks

Переводы

Введение

Элемент canvas языка HTML5, появившийся как эксперимент компании Apple, сегодня является наиболее широко поддерживаемым стандартом двухмерной веб-графики непосредственного режима. Многие разработчики используют его в разнообразных мультимедийных проектах, визуализациях и играх. Однако сложность создаваемых приложений постоянно растет, поэтому перед программистами встает проблема повышения эффективности.

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

Эта статья не освещает вопрос использования элемента canvas в языке HTML5. Сведения на эту тему можно найти в статьях об элементе canvas на ресурсе HTML5Rocks, в одном из разделов «Погружения в HTML5» и в руководстве MDN Canvas.

Испытание эффективности

Поскольку ситуация с элементом canvas в языке HTML5 быстро меняется, тесты JSPerf (их можно найти на сайте jsperf.com) позволяют проверить эффективность каждого из предложенных методов оптимизации. JSPerf – это веб-приложение, которое позволяет разработчикам создавать тесты для проверки JavaScript-кода на эффективность. Каждое такое испытание ориентировано на результат, которого необходимо достичь (например, очистка элемента canvas), и реализует несколько подходов для его достижения. JSPerf выполняет каждый из алгоритмов максимально возможное количество раз за короткий промежуток времени и возвращает статистически значимое число итераций в секунду. Чем выше полученный балл, тем лучше.

Посетители страницы JSPerf могут запустить тест в своем браузере, а система JSPerf сохранит его нормализованные результаты на сайте Browserscope (browserscope.org). Поскольку методы оптимизации, описанные в этой статье, основаны на результатах JSPerf, вы можете периодически возвращаться к ней за обновленной информацией об актуальности каждого из них. В статью встроено небольшое вспомогательное приложение, которое выводит результаты в виде графиков.

Все показатели эффективности в этой статье зависят от версии браузера. В этом заключается проблема, поскольку нам неизвестно, в какой ОС был запущен браузер, и, что еще более важно, использовалось ли для элемента canvas в языке HTML5 аппаратное ускорение в момент запуска теста эффективности. Чтобы узнать, был ли элемент canvas языка HTML5 в браузере Chrome аппаратно ускорен, введите в адресной строке about:gpu .

Предварительный рендеринг во внеэкранный элемент canvas

Если вы многократно рисуете одинаковые простейшие элементы в нескольких фреймах на экране (например, в игре), предварительный рендеринг крупных фрагментов сцены позволяет существенно повысить эффективность кода. Предварительный рендеринг – это вывод временных изображений на отдельном внеэкранном элементе canvas (или на нескольких таких элементах) с последующим переносом этих внеэкранных элементов на видимый объект canvas. Для тех, кто знаком с компьютерной графикой, этот метод также известен как список отображения.

Например, представим, что вы перерисовываете персонажа Марио, перемещающегося со скоростью 60 кадров в секунду. Можно либо перерисовывать в каждом кадре его кепку, усы и букву «М», либо выполнить предварительный рендеринг персонажа перед запуском анимации.

Вот вариант без предварительного рендеринга:

А вот вариант с предварительным рендерингом:

Обратите внимание на использование API requestAnimationFrame , который будет подробно описан в одном из следующих разделов. Приведенный ниже график иллюстрирует повышение эффективности при использовании предварительного рендеринга (см. этот тест jsperf).

Этот метод особенно эффективен, если операция рендеринга ( drawMario в приведенном выше примере) является дорогой. Хороший пример – рендеринг текста: это очень дорогая операция. Ниже продемонстрировано резкое повышение эффективности в результате ее предварительного рендеринга (см. этот тест jsperf).

При этом обратите внимание на низкую эффективность теста «Предварительный рендеринг с большим размером элемента canvas» в приведенном выше примере. При предварительном рендеринге важно убедиться, что временный элемент canvas плотно обтекает рисуемое изображение. В противном случае прирост эффективности благодаря внеэкранному рендерингу будет нивелирован потерей эффективности от копирования одного крупного элемента canvas на другой (в зависимости от размеров исходного и целевого элементов). Подходящий элемент canvas в приведенном выше тесте должен быть меньше, как показано в следующем примере.

Сравните его с большим элементом, эффективность которого ниже.

Группировка вызовов canvas

Поскольку рисование является дорогой операцией, более эффективным подходом является загрузка конечного автомата рисования длинным набором команд с их последующей выгрузкой в видеобуфер.

Например, при рисовании нескольких линий эффективнее создать один путь со всеми линиями и нарисовать его одним вызовом операции рисования. Ниже приведен код, в котором рисуются отдельные линии.

Сравните его с более эффективным кодом, в котором рисуется одна ломаная линия.

То же касается и элементов canvas в языке HTML5. Например, рисуя сложный маршрут, лучше разместить все точки на одном пути, чем обрабатывать сегменты по отдельности (см. этот тест jsperf).

Однако с элементом canvas в этом правиле связано важное исключение: если примитивы, из которых состоит объект, ограничены небольшими прямоугольниками (например, горизонтальными и вертикальными линиями), возможно, эффективнее обрабатывать их по отдельности (см. этот тест jsperf):

Отказ от ненужных изменений состояния canvas

Элемент canvas в языке HTML5 реализован на основе конечного автомата, который отслеживает, в частности, стили заливки и штрихов, а также предыдущие точки, из которых состоит текущий путь. В попытке оптимизировать эффективность отображения возникает соблазн сосредоточиться только на рендеринге графики. Однако манипуляции с конечным автоматом также могут привести к снижению эффективности.

Если, например, для рендеринга сцены используются различные цвета заливки, дешевле выполнять рендеринг по цвету, чем по размещению на элементе canvas. Чтобы обработать рисунок в полоску, можно обработать полосу, изменить цвета, обработать следующую полосу и т. д., как показано ниже.

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

Ниже приведен тест эффективности рисования чередующихся полос с помощью обоих методов (см. этот тест jsperf).

Как и ожидалось, первый подход медленнее, поскольку манипуляции с конечным автоматом обходятся дорого.

Рендеринг только разницы, а не нового состояния целиком

Как можно предположить, чем меньше информации выводится на экран, тем дешевле алгоритм. Если изображение меняется постепенно, можно существенно повысить эффективность, отрисовывая только изменения. Ниже приведен пример кода, в котором весь экран очищается перед рисованием.

Сравните его с кодом, в котором отслеживается и очищается ограничивающий прямоугольник нарисованного фрагмента.

Этот подход проиллюстрирован в приведенном ниже тесте эффективности, в котором белая точка пересекает экран (см. этот тест jsperf).

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

Этот метод также применим к попиксельному рендерингу, что продемонстрировано в этом обсуждении эмулятора Nintendo на JavaScript.

Использование многослойных элементов canvas для сложных сцен

Как уже упоминалось, рисование крупных изображений обходится дорого, и по возможности таких алгоритмов следует избегать. Помимо использования дополнительного элемента canvas для рендеринга вне экрана, как описано в разделе о предварительном рендеринге, можно также применять элементы canvas в несколько слоев. Используя прозрачность верхнего слоя, можно задействовать графический процессор для совмещения альфа-каналов во время рендеринга. Ниже показано, как настроить этот процесс с двумя элементами canvas с абсолютным размещением друг на друге.

Преимущество двух элементов canvas над одним заключается здесь в том, что при рисовании или очистке верхнего слоя фон не изменяется. Если вашу игру или мультимедийное приложение можно разделить на верхний слой и фон, их можно обрабатывать на разных элементах canvas, что существенно повысит эффективность. На графике ниже сравнивается простой случай с одним элементом canvas и случай, в котором перерисовывается и очищается только верхний слой (см. этот тест jsperf).

Часто можно воспользоваться несовершенством человеческого восприятия, обрабатывая фон только один раз или просто реже, чем верхний слой (на котором, как правило, сосредоточено внимание пользователя). Например, можно выводить верхний слой каждый раз при рендеринге, а фон – только для каждого n-ного фрейма.

Также обратите внимание на то, что такой подход применим к любому количеству составных элементов canvas, если приложение лучше работает с такой структурой.

Отказ от shadowBlur

Как и многие другие графические среды, элемент canvas в языке HTML5 позволяет разработчикам размывать примитивные объекты, но эта операция может быть очень дорогой.

В тесте ниже показана одна сцена, обработанная с тенью и без нее, с огромной разницей в эффективности (см. этот тест jsperf).

Использование разных способов очистки элемента canvas

Поскольку элемент canvas в языке HTML5 является парадигмой непосредственного режима рисования, сцену необходимо явным образом перерисовывать на каждом фрейме. Поэтому очистка элемента canvas является чрезвычайно важной операцией в разработке приложений и игр на HTML5.

Как уже упоминалось в разделе Отказ от ненужных изменений состояния canvas, очищать весь элемент canvas часто нежелательно, однако если это неизбежно, сделать это можно двумя способами: с помощью метода context.clearRect(0, 0, width, height) или специальной операции canvas.w >;.

На момент написания этой статьи метод clearRect более эффективен, чем сброс ширины, однако иногда в браузере Chrome 14 операция с canvas.width работает намного быстрее (см. этот тест jsperf).

Следуйте этой рекомендации с осторожностью, поскольку ее эффективность во многом зависит от реализации элемента canvas. Дополнительные сведения можно найти в статье Саймона Сарриса (Simon Sarris) об очистке элемента canvas.

Отказ от координат с плавающей запятой

Элемент canvas в языке HTML5 поддерживает субпиксельный рендеринг, отключить который нельзя. При рисовании с дробными координатами для выравнивания линий автоматически применяется сглаживание. Ниже показан визуальный эффект, взятый из этой статьи Себ Ли-Делисл (Seb Lee-Delisle) о субпиксельной эффективности элемента canvas.

Если эффект сглаживания спрайтов не нужен, эффективнее будет преобразовать координаты в целые числа с помощью операции Math.floor или Math.round (см. этот тест jsperf).

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

Эффективность этих методов демонстрируется в примере ниже (см. этот тест jsperf).

Обратите внимание на то, что такая оптимизация бессмысленна в случае, когда в реализации элемента canvas используется ускорение графического процессора, который позволяет быстро обрабатывать нецелые координаты.

Оптимизация анимации с помощью requestAnimationFrame

Относительно новый API requestAnimationFrame рекомендуется использовать для реализации интерактивных приложений в браузере. Вместо того чтобы заставлять браузер выполнять рендеринг с определенной частотой, можно предложить ему вызвать операцию рендеринга и сообщить вам о ее завершении. Полезный побочный эффект этого заключается в том, что когда страница не активна, браузер не выполняет рендеринг.

API requestAnimationFrame позволяет добиться скорости, близкой к 60 кадрам в секунду, но не гарантирует ее, поэтому необходимо следить за временем, прошедшим с последней операции рендеринга. Это может выглядеть приблизительно так, как показано ниже.

Помните, что такая техника использования requestAnimationFrame относится не только к элементу canvas, но и к другим технологиям рендеринга, таким как WebGL.

На момент написания статьи этот API доступен только в браузерах Chrome, Safari и Firefox, поэтому используйте одну из этих оболочек.

Большинство мобильных реализаций canvas медленные

Рассмотрим мобильные платформы. К сожалению, на момент написания этой статьи мобильная реализация canvas с ускорением на базе графического процессора есть только в браузере Safari 5.1 в бета-версии iOS 5.0. Без такого ускорения вычислительной мощности мобильных браузеров, как правило, недостаточно для современных приложений на основе canvas. В ряде описанных выше тестов JSPerf эффективность на мобильных устройствах на порядок ниже, чем на компьютерах, что существенно ограничивает число программ, способных успешно работать на разных платформах.

Заключение

В этой статье перечислен целый набор полезных методик оптимизации, которые помогут в разработке эффективных проектов HTML5 с использованием элемента canvas. Они позволят вам улучшить свой код. Если вам только предстоит написать его, загляните на сайты Chrome Experiments и Creative JS.

Илон Маск рекомендует:  Атрибут bgproperties в HTML
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL