Журнал LinuxFormat - перейти на главную

LXF94:Графическое web-приложение

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Расширяем холст)
(Рисование фигур)
Строка 83: Строка 83:
 
=== Рисование фигур ===
 
=== Рисование фигур ===
  
 +
Чтобы создать коллекцию фигур-шаблонов, заготовим пару полезных объектов: обертку холста и обертку фигуры. Обертка фигуры представляет наибольший интерес – она инкапсулирует различные сложные фигуры. Обертка холста будет следить за размещением фигур на холсте.
 +
 +
function draw() {
 +
  ic = new iCanvas(‘canvas’);
 +
  // добавьте здесь все свои фигуры
 +
  setupInteraction();
 +
}
 +
function setupInteraction() { /* мы рассмотрим ее позднее*/ }
 +
  iCanvas = {};
 +
  iCanvas = Class.create();
 +
  iCanvas.prototype = {
 +
    /* ..вырезано.. */
 +
  }
 +
  // используется для инкапсуляции фигур
 +
  iShape = {};
 +
  iShape = Class.create();
 +
  iShape.prototype = {
 +
    /* ..вырезано... */
 +
}
 +
  // рисование будет проходить в этой функции
 +
  renderShape : function() { },
 +
}
 +
 +
Полная версия исходного кода доступна по адресу http://www.linuxformat.co.uk/mag/canvas.htm, но единственной важной частью является renderShape(), так как все, что мы будем туда писать, будет родным кодом холста – другие функции (например, drawShape()) добавляются
 +
для упрощения кодирования.
 +
 +
JavaScript сопровождается HTML-страницей, которая вызывает функцию draw() в момент загрузки. Следующий пример немного прояснит ситуацию. Нарисуем простой прямоугольник – скопируйте следующий код в функцию draw() выше, где написано добавьте здесь все свои фигуры. Он создает экземпляр класса shape и использует функцию strokeRect(). Для рисования фигуры вызывается функция drawShape обертки холста:
 +
 +
box = new iShape();
 +
box.renderShape = function() {
 +
  // this.c это контекст холста
 +
  this.c.fillRect(0, 0, 100, 100);
 +
  this.c.strokeRect(0, 0, 100, 100);
 +
  this.c.stroke();
 +
}
 +
ic = new iCanvas(‘canvas’);
 +
// теперь рисуем фигуры
 +
ic.drawShape(box, {x : 200, y : 100});
 +
ic.drawShape(box, {x : 100, y : 100});
 +
ic.drawShape(box, {x : 250, y : 150});
 +
 +
Я вызывал drawShape несколько раз, чтобы показать, как можно повторно использовать фигуру после ее создания. Просто передайте объект и некоторые новые ссылки, и готово – получена новая копия фигуры.
 +
 +
Все, что делается с тэгом canvas, можно, по большей части, заложить в объект фигуры и повторно использовать его на холсте. Теперь нарисуем более сложный пример: дачный домик. Это всего лишь набор прямоугольников и треугольников:
 +
 +
house = new iShape();
 +
house.renderShape = function() {
 +
  this.c.fillStyle = ‘white’;
 +
  this.c.fillRect(0, 0, 100, 100); // ставим белый фон
 +
  this.c.strokeRect(0, 0, 100, 100);
 +
  this.c.fill();
 +
  this.c.strokeRect(20, 60, 20, 40); // дверь
 +
  // окна
 +
  this.c.fillStyle = “rgba(0, 0, 250, 0.3)”;
 +
  this.c.fillRect(60, 60, 20, 20);
 +
  this.c.fillRect(20, 20, 20, 20);
 +
  this.c.fillRect(60, 20, 20, 20);
 +
  this.c.fill();
 +
  this.c.fillStyle = “rgba(250, 0, 0, 0.3)”;
 +
  this.c.moveTo(0,0);
 +
  this.c.lineTo(50,-30);
 +
  this.c.lineTo(100,0);
 +
  this.c.fill();
 +
  this.c.stroke();
 +
}
 +
 +
fillStyle использует функцию rgba(), позволяющую нам установить прозрачность. Вы можете установить прозрачность «для всего» с помощью .globalAlpha=0.5;. Часть lineTo рисует отрезок на холсте [от текущего положения] до точки (x,y). В данном примере мы используем ее для рисования крыши.
 +
 +
Как и в предыдущем примере, мы можем повторно использовать объекты на холсте с помощью функции drawShape(). Написав
 +
 +
ic.drawShape(house, {x : 200, y : 100});
 +
ic.drawShape(house, {x : 300, y : 100});
 +
ic.drawShape(house, {x : 400, y : 100});
 +
 +
вы отстроите целую уличку.
  
 
=== Градиенты, дуги и кривые ===
 
=== Градиенты, дуги и кривые ===

Версия 15:00, 12 марта 2008

Содержание

Canvas: Холст для web-картин

Новый HTML-элемент canvas позволяет программировать графику в браузере. Дэн Фрост покажет вам, как использовать этот мощный тэг.

Рисование графики на web-страницах обычно отдавалось на откуп Flash или библиотекам на стороне сервера. Больше такому не бывать! Забудьте зависть и удовлетворите свои амбиции стать художником – по крайней мере в Firefox и Opera, благодаря тэгу <canvas>.

Впервые введенный фирмой Apple, этот тэг предоставляет программисту холст, чтобы рисовать на нем прямые, дуги, квадраты и так далее. Комбинируя простые элементы, можно получать блестящие результаты – как, вы узнаете чуть позже. В настоящий момент тэг canvas поддерживается браузерами Firefox, Opera, Safari и включен в спецификацию HTML 5 группой WHATWG (Web Hypertext Application Technology Working Group – Рабочая группа по технологии гипертекстовых приложений), что вселяет надежду на его грядущую повсеместную реализацию. В качестве краткого введения, на данном уроке я собираюсь показать, как создать простые фигуры с помощью тэга canvas, поместить эти фигуры в объектную модель и, наконец, сделать их интерактивными.

Привет, мир графики

Чтобы работать с тэгом canvas, достаточно создать небольшой HTML-файл и открыть его в Firefox. Для начала рассмотрим несложный пример. Тэг canvas добавляется на страницу обычным образом. Атрибуты «ширина» и «высота» говорят сами за себя; но вы также можете включить стандартные HTML-атрибуты, типа class, id, style и других:

<canvas id=”canvas” style=”border : thin solid black;”
width=”600” height=”400”></canvas>

Добавьте этот кусок кода на пустую HTML-страницу и откройте ее в браузере с помощью File > Open (Файл > Открыть). Все, что вы видите – это пустая область с границей, так как наш код устанавливает тэг canvas, но ничего другого не делает: просто обозначает пустой холст на странице.

Самое интересное начинается в JavaScript. JS используется для рисования линий, кривых, областей и изображений на объекте canvas. Чтобы создать две линии, добавьте это в только что созданный файл и обновите страницу в Firefox:

<canvas id=”canvas” width=”600” height=”400” style=”background-color : #c0c0c0;”></canvas>
<script>
var canvas = document.getElementById(‘canvas’);
ctx = canvas.getContext(‘2d’);
ctx.lineTo(100, 100);
ctx.lineTo(200, 300);
ctx.lineTo(300, 100);
ctx.lineTo(300, 300);
ctx.stroke();
</script>

Давайте разберемся. Сначала мы получаем HTML-элемент (или узел) по id ‘canvas’. Затем из элемента canvas мы получаем контекстный объект, его мы рассмотрим далее. Объект используется для собственно рисования.

Вот и все, что необходимо для применения тэга canvas: HTML-тэг и немного JavaScript. Вся ваша разработка может вестись с помощью Firefox и тестироваться вне сервера, так как логика и рисование находится на стороне клиента. Но что мы можем? Чтобы подстрекнуть свое воображение, гляньте на панель Dashboard от Apple (сайт http://www.apple.com/macosx/features/dashboard). Кроме того, всплывает масса мелких примеров: от реализации Paint (CanvasPaint) до восхитительных игр вроде Blobsallad (http://blobsallad.se) и Canvascope (http://www.abrahamjoffe.com.au/ben/canvascape).

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

Расширяем холст

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

Фактически мы рисуем не на объекте canvas, а на его 2D-контексте. Чтобы получить контекст canvas, мы используем функцию getContext. Контекст – это объект, содержащий функции для рисования линий, блоков цветных изображений и так далее. Линии он называет штрихами [stroke], а цветовые блоки – заливкой [fill]:

var canvas = document.getElementById(‘canvas’);
ctx = canvas.getContext(“2d”);
ctx.strokeRect(50, 50, 100, 100);
ctx.stroke();
ctx.fillRect(100, 100, 100, 100);
ctx.fill();

Большая часть функций понятна: strokeRect() рисует прямоугольник, fillRect() его заполняет. У strokeRect() и fillRect() похожие параметры – x и y верхнего левого угла прямоугольника, а также ширина и высота. Canvas ведет отсчет от левого верхнего угла, то есть 50, 50 означает 50 пикселей слева и 50 пикселей сверху. Тем, кто привык мыслить в терминах координат обычных графиков, тут легко и запутаться! Заметим также, что нам надо вызывать функции .stroke() и .fill(). Не забудьте это сделать, иначе останетесь с пустым холстом.

Цвет линий и заливки устанавливается на холсте с помощью lineStyle и fillStyle, которые принимают похожие аргументы. Самый простой способ ввести цвет – указать его: ctx.lineStyle=’red’ – или обозначить шестнадцатеричным числом: ctx.lineStyle=’#a0b0c0’;. Для получения прозрачности предусмотрен альфа-канал в функции rgba(), принимающей четыре параметра: красный, зеленый, синий и альфа. Например:

ctx.lineStyle = ‘red’;
ctx.fillStyle = ‘rgb(200, 100, 0, 0.5)’;

Когда две линии пересекаются, стиль их сочленения можно выбрать с помощью lineJoin:

ctx.lineJoin = ‘curve’;

Две последние важные концепции – перенос и поворот. Перенос – это передвижение в другую точку холста; поворот, очевидно, и есть поворот холста. Оба действия производятся до того, как вы начнете рисовать. Например, если вы хотите нарисовать прямоугольник под 45°, то сначала вам надо добавить функцию поворота:

ctx.rotate(-45 * Math.PI / 180);
ctx.strokeRect(50, 50, 100, 100);
ctx.stroke();

Все эти настройки внутри холста, то есть lineStyle, fillStyle, поворот и перенос, можно сохранять в стеке состояний, а потом брать их оттуда. Это позволяет понаделать кучу стилевых настроек, а затем разом их отменить, закончив рисование:

ctx.save(); // Сохранить текущее состояние, чтобы мы могли его восстановить
ctx.rotate(-45 * Math.PI / 180);
ctx.lineStyle = ‘blue’;
ctx.strokeRect(50, 50, 100, 100); // нарисовать прямоугольник
ctx.stroke();
ctx.restore(); // восстановить lineStyle и поворот

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

Рисование фигур

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

function draw() {
 ic = new iCanvas(‘canvas’);
 // добавьте здесь все свои фигуры
 setupInteraction();
}
function setupInteraction() { /* мы рассмотрим ее позднее*/ }
 iCanvas = {};
 iCanvas = Class.create();
 iCanvas.prototype = {
    /* ..вырезано.. */
 }
 // используется для инкапсуляции фигур
 iShape = {};
 iShape = Class.create();
 iShape.prototype = {
   /* ..вырезано... */
}
 // рисование будет проходить в этой функции
 renderShape : function() { },
}

Полная версия исходного кода доступна по адресу http://www.linuxformat.co.uk/mag/canvas.htm, но единственной важной частью является renderShape(), так как все, что мы будем туда писать, будет родным кодом холста – другие функции (например, drawShape()) добавляются для упрощения кодирования.

JavaScript сопровождается HTML-страницей, которая вызывает функцию draw() в момент загрузки. Следующий пример немного прояснит ситуацию. Нарисуем простой прямоугольник – скопируйте следующий код в функцию draw() выше, где написано добавьте здесь все свои фигуры. Он создает экземпляр класса shape и использует функцию strokeRect(). Для рисования фигуры вызывается функция drawShape обертки холста:

box = new iShape();
box.renderShape = function() {
 // this.c это контекст холста
 this.c.fillRect(0, 0, 100, 100);
 this.c.strokeRect(0, 0, 100, 100);
 this.c.stroke();
}
ic = new iCanvas(‘canvas’);
// теперь рисуем фигуры
ic.drawShape(box, {x : 200, y : 100});
ic.drawShape(box, {x : 100, y : 100});
ic.drawShape(box, {x : 250, y : 150});

Я вызывал drawShape несколько раз, чтобы показать, как можно повторно использовать фигуру после ее создания. Просто передайте объект и некоторые новые ссылки, и готово – получена новая копия фигуры.

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

house = new iShape();
house.renderShape = function() {
 this.c.fillStyle = ‘white’;
 this.c.fillRect(0, 0, 100, 100); // ставим белый фон
 this.c.strokeRect(0, 0, 100, 100);
 this.c.fill();
 this.c.strokeRect(20, 60, 20, 40); // дверь
 // окна
 this.c.fillStyle = “rgba(0, 0, 250, 0.3)”;
 this.c.fillRect(60, 60, 20, 20);
 this.c.fillRect(20, 20, 20, 20);
 this.c.fillRect(60, 20, 20, 20);
 this.c.fill();
 this.c.fillStyle = “rgba(250, 0, 0, 0.3)”;
 this.c.moveTo(0,0);
 this.c.lineTo(50,-30);
 this.c.lineTo(100,0);
 this.c.fill();
 this.c.stroke();
}

fillStyle использует функцию rgba(), позволяющую нам установить прозрачность. Вы можете установить прозрачность «для всего» с помощью .globalAlpha=0.5;. Часть lineTo рисует отрезок на холсте [от текущего положения] до точки (x,y). В данном примере мы используем ее для рисования крыши.

Как и в предыдущем примере, мы можем повторно использовать объекты на холсте с помощью функции drawShape(). Написав

ic.drawShape(house, {x : 200, y : 100});
ic.drawShape(house, {x : 300, y : 100});
ic.drawShape(house, {x : 400, y : 100});

вы отстроите целую уличку.

Градиенты, дуги и кривые

Взаимодействие с холстом


Ресурсы

Попробуйте еще

Не останавливайтесь на достигнутом – попробуйте другие функции...

  • createPattern() превращает изображения или другие объекты canvas в шаблоны для многократного использования.
  • clearRect(x2,y1,x2,y2) очищает кусок холста.
  • clip() создает путь отсечения так, что вы можете ограничить холст определенной фигурой, например, кругом или сложным многоугольником.
Персональные инструменты
купить
подписаться
Яндекс.Метрика