Основы HTML5: Часть 4. Завершающий штрих – Canvas

Возможности тега Canvas

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

Грейс Уолкер, ИТ-консультант, Walker Automated Services

Грейс Уолкер (Grace Walker) является сотрудником компании Walker Automated Services (Чикаго, штат Иллинойс), где выполняет обязанности ИТ-консультанта. Грейс Уолкер обладает разнообразным и обширным опытом. В ИТ-сфере она работала в качестве менеджера, администратора, программиста, преподавателя, бизнес-аналитика, технического аналитика и Web-разработчика в самых различных областях, включая телекоммуникации, образование, финансовые услуги и программное обеспечение.



16.05.2012

Автор HTML5-материалов сочетает в одном лице бесстрашного проектировщика и рационального разработчика. Цель его деятельности состоит в построении эффективных RIA-приложений (Rich Internet Application — насыщенные Интернет-приложения), особенно таких, которые обладают насыщенными пользовательскими интерфейсами. Говоря о построении эффективных приложений, я в первую очередь имею в виду создание системных и систематических усовершенствований, которые «цифровым образом» обеспечивают диалог между владельцем сайта, агентами этого владельца и посетителями сайта.

Совершенствование квалификационных навыков по данной тематике

Данная статья является частью учебной программы по совершенствованию квалификационных навыков. См. Основы HTML5.

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

Как вы уже убедились, технологии HTML5 специально созданы для мира «one web world», отличительными особенностями которого являются межплатформенные возможности, конвергентные коммуникации, унифицированный язык, вездесущая компьютеризация и открытые системы. Первые три части данной серии статей были посвящены таким темам, как семантические теги, надлежащие методы написания кода, роль ввода информации в жизненно важном процессе конверсии посетителей, наилучшие методики управления сайтами. Все эти темы формируют фундамент для RIA-приложений — организованным и рациональным образом. Общая идея всех статей состоит в том, что создание насыщенных пользовательских возможностей и управление ими жизненно необходимо владельцам Web-сайта для достижения своих «производственных» целей. HTML5-тег Canvas играет важнейшую роль в создании эффективных RIA-приложений.

Часто используемые сокращения

  • 2D: Two-dimensional (двухмерный).
  • Ajax: Asynchronous JavaScript + XML (технология Ajax).
  • API: Application programming interface (Интерфейс прикладного программирования, API-интерфейс).
  • HTML: Hypertext Markup Language (язык гипертекстовой разметки, язык HTML).
  • HTML5: HTML, версия 5.
  • UI: User interface (Интерфейс пользователя).

Что такое Canvas

HTML5-тег Canvas является исключительно полезным инструментом для рисования и анимации. Тег Canvas использует технологию JavaScript для рисования графических объектов непосредственно на Web-странице. Canvas представляет собой прямоугольную область, задаваемую и контролируемую разработчиком. Эта область позволяет осуществлять допускающую использование сценариев визуализацию двухмерных 2D-форм и растровых изображений.

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


Координаты Canvas

Обязательным условием для создания изображений в среде Canvas является знакомство с координатной сеткой (координатной плоскостью). Измерения пространственной области по ширине и высоте задаются в пикселах. В среде Canvas используются координаты x и y. Верхний левый угол области Canvas имеет координаты x=0, y=0.

По умолчанию размеры прямоугольной области Canvas имеют ширину 300 пикселов и высоту 150 пикселов, но вы можете задать точные размеры тега Canvas посредством указания его ширины и высоты. Схема на рисунке 1 демонстрирует организацию координатного пространства по x и y.

Рисунок 1. Координаты Canvas
Square with diagonal and horizontal lines through it showing the coordinates at each intersection.

На рисунке 1 показана область Canvas размером 100 х 100 пикселов.

  • Левый верхний угол имеет координаты x=0, y=0.
  • Значение координаты x увеличивается по горизонтали, а значение координаты y увеличивается по вертикали.
  • Правый нижний угол имеет координаты x=100, y=100.
  • Центральная точка имеет координаты x=50, y=50.

Начало работы

Чтобы поместить что-либо в зону Canvas, сначала нужно задать область Canvas в HTML-файле. Чтобы нарисовать свои изображения, вы должны создать JavaScript-код, который обращается к тегу <canvas> и коммуницирует с API-интерфейсом HTML5 Canvas.

Базовая структура тега <canvas> имеет следующий вид:

<canvas id="myCanvas" width="200" height="200"></canvas>

Тег canvas имеет два собственных атрибута: width (высота) и height (ширина). Кроме того, тег Canvas имеет все ключевые HTML5-атрибуты, такие как class, id и name. Атрибут id используется в показанном выше коде. JavaScript-код использует созданный здесь идентификатор id тега Canvas для обозначения области Canvas, на которой будет осуществляться рисование. JavaScript-код выявляет надлежащую область Canvas с помощью метода document.getElementById(), как показано ниже.

var canvas = document.getElementById("myCanvas");

Каждый тег Canvas должен иметь определение контекста, как показано ниже. В настоящее время официальная спецификация распространяется только на 2D-среду.

var context = canvas.getContext("2d");

После идентификации надлежащей области Canvas и указания ее контекста можно приступать к рисованию.


Инструменты рисования, эффекты и преобразования

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

  • Линии.
  • Прямоугольники.
  • Дуги.
  • Кривые Безье и квадратичные кривые.
  • Круги и полукруги.

Мы будем использовать следующие эффекты Canvas:

  • Заполнения и мазки.
  • Линейные и радиальные градиенты.

Будут рассмотрены следующие преобразования:

  • Масштабирование.
  • Поворот.
  • Перемещение.

Рисование линий

Чтобы нарисовать линию в среде Canvas, воспользуйтесь методами moveTo(), lineTo() и stroke(). Кроме того, используйте метод beginPath() для восстановления текущего маршрута.

  • context.beginPath();
  • Context.moveTo(x,y);
  • Context.lineTo(x,y);
  • Context.stroke(x,y);

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

Метод moveTo() задает начальную точку, в которой должен начинаться новый субмаршрут. Метод lineTo() создает субмаршруты. Внешней вид линии можно изменить с помощью тегов lineWidth и strokeStyle. Тег lineWidth меняет толщину линии, а тег strokeStyle меняет цвет линии.

На рисунке 2 показаны три линии, нарисованные с использованием разных цветов.

Рисунок 2. Область Canvas с линиями разного цвета
A canvas showing three lines in different colors

Линии на рисунке 2 были созданы с помощью кода, показанного в листинге 1. Синяя линия с закругленными концами создается следующим образом. Сначала указывается необходимость начала нового маршрута: context.beginPath(). Затем используются следующие методы:

  • context.moveTo(50, 50), помещает начало маршрута в точку с координатами(x=50, y=50).
  • context.lineTo(300,50), специфицирует конечную точку линии.
  • context.lineWidth = 10, специфицирует ширину линии.
  • context.strokeStyle = "#0000FF", специфицирует цвет линии.
  • context.lineCap = "round", делает концы закругленными.
  • context.stroke(), осуществляет фактическое рисование линии на Canvas.

Все описываемые линии имеют длину по 50 пикселов, хотя и создается впечатление разной длины — это визуальная иллюзия, порождаемая так называемыми «завершителями линий» (line cap). Имеются три возможных типа завершителя:

  • Context.round (синий).
  • Context.square (зеленый).
  • Context.butt(фиолетовый — по умолчанию).

По умолчанию используется завершитель butt. При использовании закругленных или квадратных завершителей длина линии увеличивается на величину, равную ширине этой линии. Например, линия длиной 200 пикселов и шириной 10 пикселов с закругленными или квадратными завершителями будет иметь результирующую длину 210 пикселов, поскольку каждый завершитель добавляет по 5 пикселов на каждом конце линии. Линия длиной 200 пикселов и шириной 20 пикселов с закругленными или квадратными завершителями будет иметь результирующую длину 220 пикселов, поскольку каждый завершитель добавляет по 10 пикселов на каждом конце линии.

Чтобы лучше понять, как осуществляется рисование линий, выполните и измените код на рисунке 1.

Листинг 1. Создание в среде Canvas трех линий разного цвета
<!DOCTYPE HTML>
<html>
    <head>
	    <title>Line Example</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #9C9898;
            }
        </style>
        <script>
            
          window.onload = function() {
                var canvas = document.getElementById("myCanvas");
                var context = canvas.getContext("2d");
                
                // blue line with round ends
                context.beginPath();
                context.moveTo(50, 50);
                context.lineTo(300,50);
                context.lineWidth = 10;
                context.strokeStyle = "#0000FF"; 
                context.lineCap = "round";
                context.stroke();

                // green line with square ends
                context.beginPath();
                context.moveTo(50, 100);
                context.lineTo(300,100);
                context.lineWidth = 20;
                context.strokeStyle = "#00FF00"; 
                context.lineCap = "square";
                context.stroke();

                // purple line with butt ends
                context.beginPath();
                context.moveTo(50, 150);
                context.lineTo(300, 150);
                context.lineWidth = 30;
                context.strokeStyle = "#FF00FF"; 
                context.lineCap = "butt";
                context.stroke();
            };
        </script>
    </head>
    <body>
        <canvas id="myCanvas" width="400" height="200">
        </canvas>

    </body>
</html>

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

Для создания прямоугольной области в Canvas имеются три метода:

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

Для каждого из этих трех методов x и y задают положение на Canvas относительно левого верхнего угла прямоугольника (x=0, y=0), а width и height задают ширину и высоту прямоугольника, соответственно.

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

Рисунок 3. Прямоугольная область Canvas
Yellow-filled box with a thick black square rectangle and a thin rectangle in it

Метод fillRect() создает прямоугольник, заполненный цветом по умолчанию (черный). Метод clearRect() создает прямоугольную область в центре первого прямоугольника. Она размещается в центре прямоугольника, сформированного методом fillRect(). Метод strokeRect создает прямоугольник, который имеет только видимую черную границу.

Листинг 2. Код для рисования прямоугольных областей на Canvas
<!DOCTYPE HTML>
<html>
<head>
<title>Rectangle Example</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #000000;
                background-color: #ffff00;
            }
        </style>
<script type="text/javascript">
function drawShape(){
   var canvas = document.getElementById('myCanvas');

    var context = canvas.getContext('2d');


    context.fillRect(25,25,50,50);
    context.clearRect(35,35,30,30);
    context.strokeRect(100,100,50,50);

}
</script>
</head>
<body onload="drawShape();">
   <canvas id="myCanvas" width="200" height="200"></canvas>
</body>
</html>

Рисование дуг, кривых, кругов и полукругов

Для рисования кругов и полукругов применяется метод arc(). Метод arc() имеет шесть аргументов:

context.arc(centerX, centerY, radius, startingAngle, endingAngle, antiClockwise);

Аргументы centerX и centerY задают координаты центра круга. Аргумент radius представляет собой радиус, т.е. расстояние по прямой от центра до окружности. Создаваемая дуга будет частью заданного круга. Аргументы startAngle и endAngle представляют собой начальную и конечную точку дуги, соответственно (в радианах). Аргумент anticlockwise имеет тип Boolean. Если этот аргумент имеет значение true, то рисование дуги осуществляется против часовой стрелки; если он имеет значение false, то рисование дуги осуществляется по часовой стрелке.

Чтобы нарисовать круг с помощью метода arc() присвойте начальному углу значение 0, а конечному углу — значение 2*PI, как показано ниже.

context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);

Чтобы нарисовать полукруг с помощью метода arc() присвойте начальному углу значение startingAngle + PI, как показано ниже.

context.arc(centerX, centerY, radius, startingAngle, startingAngle + Math.PI, false);

Квадратичная кривая

Квадратичная кривая создается с помощью метода quadraticCurveTo(), как показано ниже. Квадратичная кривая задается точкой контекста, контрольной точкой и конечной точкой. Контрольная точка задает кривизну кривой.

context.moveTo(x, y);
context.quadraticCurveTo(controlX, controlY, endX, endY);

Кривая Безье

Кривая Безье имеет начальную и конечную точки, как и квадратичная кривая, но в отличие от нее имеет две контрольные точки.

context.moveTo(x, y);
context.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);

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

На рисунке 4 показаны (слева направо): дуга, квадратичная кривая, кривая Безье, полукруг и круг.

Рисунок 4. Дуга, кривые и круг
Image showing arcs, curves, circles, and semicircles on the canvas

Изображение на рисунке 4 было создано с помощью кода, показанного в листинге 3.

Листинг 3. Код для дуги, кривой и круга
<!DOCTYPE HTML>
<html>
    <head>
	<title>Arcs, Curves, Circles, & Semicircles</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #9C9898;
            }
        </style>
<script>
function drawArc(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 100;
    var centerY = 160;
    var radius = 75;
    var startingAngle = 1.1 * Math.PI;
    var endingAngle = 1.9 * Math.PI;
    var counterclockwise = false;
 
    context.arc(centerX, centerY, radius, startingAngle, 
        endingAngle, counterclockwise);
 
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawQuadratic(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    context.moveTo(200, 150);
 
    var controlX = 288;
    var controlY = 0;
    var endX = 388;
    var endY = 150;
 
    context.quadraticCurveTo(controlX, controlY, endX, endY);
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawBezier(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    context.moveTo(350, 350);
 
    var controlX1 = 440;
    var controlY1 = 10;
    var controlX2 = 550;
    var controlY2 = 10;
    var endX = 500;
    var endY = 150;
 
    context.bezierCurveTo(controlX1, controlY1, controlX2, 
        controlY2, endX, endY);
 
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawCircle(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 450;
    var centerY = 375;
    var radius = 70;
 
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
 
    context.fillStyle = "#800000";
    context.fill();
    context.lineWidth = 5;
    context.strokeStyle = "black";
    context.stroke();
};


function drawSemicircle(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 100;
    var centerY = 375;
    var radius = 70;
    var lineWidth = 5;
 
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, Math.PI, false);
    context.closePath();
 
    context.lineWidth = lineWidth;
    context.fillStyle = "#900000";
    context.fill();
    context.strokeStyle = "black";
    context.stroke();
};

window.onload = function (){
drawArc();
drawQuadratic(); 
drawBezier(); 
drawCircle(); 
drawSemicircle()
}
</script>
    </head>
    <body>
        <canvas id="myCanvas" width="600" height="500">
        </canvas>
    </body>
</html>

Преобразование: перемещение, масштабирование и вращение

Методы translate(), scale() и rotate() изменяют текущее состояние изображения. Метод translate(x, y) перемещает объекты на Canvas в другую точку координатной сетки. В методе translate(x,y) координаты (x,y) обозначают, соответственно, количество пикселов, на которое следует переместить изображение в направлении x, и количество пикселов, на которое следует переместить изображение в направлении y.

Если в точке (15,25) вы рисуете изображение с помощью метода drawImage(), то можете использовать метод translate() с аргументами (20,30), который помещает это изображение в точку (15+20, 25+30) = (35, 55).

Метод scale(x,y) изменяет размеры изображения. Аргумент x задает коэффициент масштабирования по горизонтали, а аргумент y задает коэффициент масштабирования по вертикали. Например, метод scale(1.5, .75) создаст изображение, которое по координате x будет больше исходного изображения на 50%, а по координате y составит лишь 75% от размера исходного изображения. Метод rotate(angle) поворачивает объект на заданный угол.

На рисунке 5 показан результат применения методов translate(), scale() и rotate().

Рисунок 5. Использование преобразований
Image showing a blue box with the words mirror image reading from the right.

В листинге 4 показан код, с помощью которого было создано изображение на рисунке 5.

Листинг 4. Код для создания преобразований
<!DOCTYPE HTML>
<html>
<head>
<Title>Transformations Example</title>
<script>
 
window.onload = function() {
	var canvas=document.getElementById("myCanvas");
	var context=canvas.getContext("2d");
 
	var rectWidth = 250;
	var rectHeight = 75;
 
	// translate context to center of canvas
	context.translate(canvas.width/2,canvas.height/2); 		
 
	// half the y component 
	context.scale(1,0.5);

	// rotate 45 degrees clockwise
	context.rotate(-Math.PI/4); 
 
	context.fillStyle="blue";
	context.fillRect(-rectWidth/2,-rectHeight/2,
		rectWidth,rectHeight);


	// flip context horizontally
	context.scale(-1,1);
 
	context.font="30pt Calibri";
	context.textAlign="center";
	context.fillStyle="#ffffff";
	context.fillText("Mirror Image",3,10);

}
 
</script>
</head>
<body>
	<canvas id="myCanvas" width="400" height="400"></canvas>
</body>
</html>

Градиенты

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

Линейный градиент реализуется с помощью метода createLinearGradient(). Метод createLinearGradient(x0,y0,x1,y1) создает градиент вдоль прямой линии, задаваемой двумя точками: (x0,y0) и (x1,y1), которые являются начальной и конечной точками градиента, соответственно. Этот метод возвращает объект.

Цветовой градиент способен охватывать множество цветов. Метод addcolorStop(offset, color) задает стоп-цвет (color-stop), до которого указанный цвет должен градиентно изменяться с заданным офсетом (offset). Метод addColorStop() позволяет задать офсет от 0 до 1, где начинается переход к следующему цвету. Значение 0 — это офсет на одном конце градиента; значение 1 — это офсет на другом конце градиента. После задания цветового градиента градиентный объект может быть назначен методу fillStyle(). Метод fillText() позволяет рисовать текст с градиентным изменением цвета.

Радиальный градиент —createradialGradient(x0,y0,r0,x1,y1,r1)— сочетает два цвета или более в круговом или коническом шаблоне с помощью шести аргументов:

  • (x0,y0). Центр первой окружности конуса.
  • r0. Радиус первой окружности.
  • (x1,y1). Центр второй окружности конуса.
  • r1. Радиус второй окружности.

На рисунке 6 показано четыре градиента: линейный градиент, градиент текста, линейный диагональный градиент и радиальный градиент.

Рисунок 6. Примеры градиентов
Drawing gradients on the canvas

Изображение на рисунке 6 было создано с помощью кода, показанного в листинге 5.

Листинг 5. Пример кода для формирования градиента
<!doctype>
<html>
<head>
<title>Gradient Example</title>
<script>
   window.onload = function() {
      var canvas = document.getElementById("myCanvas");

      var context = canvas.getContext("2d");

      //Let's try the gradient on a rectangle

      // Create a linear gradient 
      var fillColor = context.createLinearGradient(50,50, 150,50);

      // Set  gradient colors
      fillColor.addColorStop(0.15,"red");
      fillColor.addColorStop(0.35,"black");
      fillColor.addColorStop(0.65,"green");
      fillColor.addColorStop(0.87,"yellow");

      // Assign gradient object to fillstyle
      context.fillStyle= fillColor;

      // Draw rectangle
      context.fillRect(50,50,100,100);

      // With text  

      var fillColorText = context.createLinearGradient(300,50,600,50);
 
      fillColorText.addColorStop(0.2,"red");
      fillColorText.addColorStop(0.4,"black");
      fillColorText.addColorStop(0.6,"green");
      fillColorText.addColorStop(0.8,"yellow");


     context.fillStyle= fillColorText;

      context.font="40px verdana";
      context.textBaseline="top";
      context.fillText("With text too!", 300,50)

      // Gradient on a diagonal
      var fillColordiagonal = context.createLinearGradient(50,200, 100,450);

      // Gradient colors
      fillColordiagonal.addColorStop(0.2,"red");
      fillColordiagonal.addColorStop(0.4,"black");
      fillColordiagonal.addColorStop(0.6,"green");
      fillColordiagonal.addColorStop(0.75,"yellow");

      // Assign gradient object to fillstyle
      context.fillStyle= fillColordiagonal;

      // Draw  rectangle
      context.fillRect(50,225, 100,250);

      // Draw radial gradient
     fillColorRadial = context.createRadialGradient(450,300,0, 450,300,200);
     fillColorRadial.addColorStop(0, "red");
     fillColorRadial.addColorStop(0.2, "black");
     fillColorRadial.addColorStop(0.4, "green");
     fillColorRadial.addColorStop(0.7, "yellow");
     context.fillStyle = fillColorRadial;
     context.rect(300,200,500,400);
     context.fill();

}
</script>
</head>
<body>
<div>
    <p><canvas id="myCanvas" width="600" height="400"></canvas></p>
</div>
</body>
</html>

Кадрирование изображения

Вы можете изменять изображения посредством кадрирования его определенных областей. Кадрирование в среде Canvas обеспечивается перегрузкой метода the drawImage(). Метод drawImage() имеет три опции. Вы можете использовать конфигурации с тремя, пятью или девятью аргументами.

Конфигурация с тремя аргументами —drawImage(image, dx, dy)— формирует на Canvas изображение с целевыми координатами (dx, dy). Эти координаты задают левый верхний угол результирующего изображения.

Конфигурация с пятью аргументами —drawImage(image, dx, dy, dw, dh)— формирует ширину и высоту целевого изображения. Исходное изображение масштабируется таким образом, чтобы результирующее изображение имело заданные ширину и высоту.

Конфигурация с девятью аргументами —drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)— обрезает исходное изображение до прямоугольной области с началом в точке с координатами (sx,sy), которая имеет ширину и высоту (sw,sh), а затем масштабирует его таким образом, чтобы результирующее изображение имело ширину и высоту (dw,dh), и помещает его на Canvas в точку (dx,dy).

На рисунке 7 показано изображение, которое мы подвергнем кадрированию.

Рисунок 7. Кадрирование изображения
A portrait of Napoleon riding a horse.

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

Рисунок 8. Итоговое кадрированное изображение
Same Napoleon image but with a headshot in the upper left and a smaller image in the bottom right

Изображение на рисунке 8 было создано с помощью кода, показанного в листинге 6. Перед исполнением этого кода не забудьте загрузить изображение Napolean.png, которое было использовано в данном примере.

Листинг 6. Код для кадрирования примера изображения
<!doctype>
<html>
<head>
<title>Crop Example</title>
<script type="text/javascript">
  window.onload = function()  {
  var canvas=document.getElementById("cropNapolean");
	var context=canvas.getContext("2d");
 
	var imageObj = new Image();
	imageObj.onload = function() {
	// draw image to cover the entire canvas
		context.drawImage(imageObj,0,0, 600, 400);
 
	// draw small image in bottom right corner
		var sourceX = 0;
		var sourceY = 0;
		var sourceWidth = 1200;
		var sourceHeight = 801;
		var destX = 300;
		var destY = 200;
		var destWidth = sourceWidth - 900;
		var destHeight = sourceHeight - 600;
 
		context.drawImage(imageObj, sourceX, sourceY, sourceWidth,
			sourceHeight, destX, destY, destWidth, destHeight);
	
	 //draw Napolean's head only
		var sourceNapoleanX = 460;
		var sourceNapoleanY = 25;
		var sourceNapoleanWidth = 250;
		var sourceNapoleanHeight = 175;
		var destNapoleanX = 0;
		var destNapoleanY = 0;
		var destNapoleanWidth = sourceNapoleanWidth - 150 ;
		var destNapoleanHeight = sourceNapoleanHeight - 100;
 
        context.drawImage(imageObj, sourceNapoleanX, sourceNapoleanY, 
             sourceNapoleanWidth, sourceNapoleanHeight, 
               destNapoleanX, destNapoleanY, 
                 destNapoleanWidth, destNapoleanHeight);
	}
	imageObj.src = "Napoleon.png";	
}
</script>
  
  </head>
<body>
  <div>
    <p><canvas id="cropNapolean" width="600" height="400"></canvas></p>
  </div>
</body>
</html>

Анимация с использованием изображений на нескольких тегах Canvas

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

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

Для создания анимации выполните следующие шаги.

  1. Создайте среду Canvas для какой-либо фигуры, которая уже была нарисована раньше.
  2. Сохраните состояние Canvas, чтобы гарантировать использование исходного состояния при каждом рисовании кадра.
  3. Выполните необходимые операции по рендерингу кадров.
  4. Если вы сохранили состояние, восстановите его перед рисованием нового кадра.

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

На рисунке 9 показан один кадр анимации пловца с помощью нескольких сред Canvas. Вода находится на одной среде Canvas, а пловец находится на другой среде Canvas.

Рисунок 9. Анимация с использованием изображений на нескольких тегах Canvas
Stick figure on a blue gradient background.

Пловец создается с помощью кода, показанного в листинге 7. Для создания воды используется линейный градиент. Вода имеет четыре оттенка синего цвета, что обеспечивает приемлемую иллюзию воды. Движение пловца создается посредством использования значений positionX и positionY, которые меняют позу изображения. Создание головы пловца осуществляется с помощью метода arc(). Ноги и руки пловца создаются посредством рисования линий и последующего изменения их положений с помощью lineTo(). Изменения туловища осуществляются посредством изменения положения с помощью moveTo(). Поскольку мы имеем дело с анимацией, то, чтобы увидеть движение пловца, необходимо исполнить данный код.

Листинг 7. Пример анимации
<!DOCTYPE HTML>
<html>
    <head>
	<title>Animation & Multiple Canvas Example</title>
<script>            
// Water canvas
function  drawWater() {
    var canvasWater = document.getElementById("myWaterCanvas");
    var contextWater = canvasWater.getContext("2d");
	contextWater.globalAlpha = .50 ;

    // Create a linear gradient fill
    var linearGrad = contextWater.createLinearGradient(0,0,400,400);
    linearGrad.addColorStop(0, '#0000ff'); // sets the first color
    linearGrad.addColorStop(.25, '#0099ff'); // sets the second color
    linearGrad.addColorStop(.50, '#00ccff'); // sets the third color
    linearGrad.addColorStop(.75, '#00ffff'); // sets the fourth color
    contextWater.fillStyle = linearGrad;
    contextWater.fillRect(0,0,400,400);
}

// Swimmer canvas
           setInterval(drawSwimmer, 30);
           var positionX = 0;
           var positionY = 0;
            
          function  drawSwimmer(){
                var canvasSwimmer = document.getElementById("mySwimmerCanvas");
                var contextSwimmer = canvasSwimmer.getContext("2d");
                contextSwimmer.clearRect(0,0,400,400);

                if (positionX < 30)
                  {
                     positionX += 1;
                     positionY += 1;
                  }
                else
                {
                     positionX = 0;
                     positionY = 0;
                }
               

                contextSwimmer.save();

               // draw circle for head
               var centerX = 200;
               var centerY = 50;
               var radius = 20;
 
               contextSwimmer.beginPath();
               contextSwimmer.arc(centerX, centerY+positionY, 
			                         radius, 0, 2 * Math.PI, false);
 
               contextSwimmer.fillStyle = "#000000";
               contextSwimmer.fill();
               contextSwimmer.lineWidth = 5;


                // torso
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200,70+positionY);
                contextSwimmer.lineTo(200,175);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image right arm
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 100);
                contextSwimmer.lineTo(175-positionX,140-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image left arm
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 100);
                contextSwimmer.lineTo(225+positionX,140-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image right leg
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 175);
                contextSwimmer.lineTo(190-positionX,250-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();


               // image left leg
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 175);
                contextSwimmer.lineTo(210+positionX,250-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

                contextSwimmer.restore();

           };

</script>

</head>
    <body onload="drawWater();">
        <canvas id="myWaterCanvas" width="400" height="400" style="z-index: 2; 
		              position:absolute;left:0px;top:0px;">
        </canvas>
        <canvas id="mySwimmerCanvas" width="400" height="400" style="z-index: 1; 
		              position:absolute;left:0px;top:0px;">
        </canvas>

    </body>
</html>

Заключение

HTML5-тег Canvas играет центральную роль при создании RIA-приложений на базе браузеров. Он предоставляет практичную среду рисования, базирующуюся на технологии JavaScript и ограниченную лишь воображением разработчика. Эта среда не слишком сложна для освоения. Кроме того, в Интернете имеется множество инструментов поддержки, облегчающих обучение и подготовку, включая краткие инструкции, блоги, онлайновые статьи, видео- и текстовые пособия, типовые приложения.

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


Загрузка

ОписаниеИмяРазмер
Изображение НаполеонаNapoleon.zip2045 KБ

Ресурсы

Научиться

  • Оригинал статьи: HTML5 fundamentals, Part 4: The final touch.
  • Create great graphics with the HTML5 canvas (Создание впечатляющих графических материалов с помощью HTML5 Canvas, developerWorks, февраль 2011 г.). Руководство по разработке графических приемов и процессов.
  • Демонстрация Canvas Pixel Manipulation от организации Safari Dev Centerthat — прекрасный пример использования Canvas для создания эффективных визуальных активов.
  • Раздел HTML Living Standard на сайте организации WHATWG позволяет ознакомиться с состоянием разработки спецификаций HTML5 Canvas.
  • Справочник HTML5 Canvas на сайте W3Schools.com содержит несколько полезных упражнений, помогающих углубить знания по Canvas.
  • Руководство по Canvas на ресурсе MDN Docs — отличное базовое руководство, отражающее опыт разработки организации Mozilla.
  • Let's Call It A Draw(ing Surface)— инновационное руководство по базовым концепциям HTML5-тега Canvas.
  • Следите за мероприятиями и трансляциями по техническим вопросам на Web-сайте developerWorks, посвященными различным продуктам IBM и актуальным темам ИТ-отрасли.
  • Материалы developerWorks на ресурсе Twitter.

Получить продукты и технологии

  • Dojo Toolkit— это библиотека JavaScript-модулей с открытым исходным кодом, которая помогает быстро разрабатывать межплатформенные приложения и Web-сайты на базе JavaScript/Ajax.

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, Open source
ArticleID=816610
ArticleTitle=Основы HTML5: Часть 4. Завершающий штрих – Canvas
publish-date=05162012