HTML это основа современного веба. И сегодня, когда пришло
время интерактивных изображений, SVG и Canvas часто являются предметом выбора – Flash уже забыт, Silverlight – редкий единорог который обитает на
окраине Веба, ну и путь еще есть парочку небольших сторонних библотек.
Минусы и плюсы каждого из них хорошо документированы, но по сути, SVG лучше подходит для создания и
обработки интеракивных элементов. Это связано с тем, что SVG описывается векторным XML-форматом, и
когда изображение загружено на странице с использованием тэга <svg>, каждый
элемент в нем становится полноценным элементов SVG DOM.
В данной статье, я представлю вам GraphicsJS, новую и мощную JavaScript библиотеку для рисования с открытым
исходным кодом, которая базируется на SVG (с поддержкой VML для старых версий IE). Я начну с
короткого введения, в котором расскажу о базовых принципах, а после этого продемонстрирую
функциональность библиотеки с помощью двух коротких, но тем не менее
впечатляющих примеров: первый – это исскуство, в то время как второй
иллюстрирует как программно создавать игру убийцу времени менее чем за 50 строк
кода.
Почему GraphicsJS
Существует много библиотек, которые предназначены
для работы с SVG: Raphaël, Snap.svg, и BonsaiJS это одни из лучших. Каждая
из них имеет свои преимущства и недостатки, но сравнивать их в данной статье я
не буду. Вместо этого я опишу GraphicsJS,
поэтому давайте я объясню что делает библиотеку хорошей и особенной.
Во первых, GraphicsJS легковесная и имеет очень
гибкое JavaScript API.
Оно реализует большое разнообразие логики для работы с текстом, имеет отличный
виртуальный DOM – отделенный от HTML DOM реализации конкретного браузера.
Во-вторых, это новая библиотека JavaScript с
открытым исходным кодом, которую совсем
недавно выпустил AnyChart, один из лучших
разработчиков в сфере визуализации интерактивных данных. Данный разработчик
использовал GaphicsJS для отображения диаграмм в своих коммерческих продуктах на
протяжении как минимум последних трех лет (со времен появления AnyChart 7.0). Таким образом,
данная библиотека хорошо протестирована в реальных условиях (Отречение: я ни в
коем случае не являюсь ни R&D в AnyChart ни
главный разработчик GaphicsJS).
В-третьих, в отличие от прочих библиотек AnyChart, библиотека GraphicsJS может
использоваться бесплатно в коммерческих и некомерческих проектах. Она доступна
в GitHub под лицензией Apache.
В четвертых, работает с любыми браузерами, и
поддерживает IE 6.0+, Safari 3.0+, Firefox 3.0+ и Opera 9.5+. Она использует VML в
старых версиях IE и SVG во всех остальных браузерах.
Наконец, GraphicsJS позволяет комбинировать
графику и анимацию для получения лучшего эффекта. Посмотрите на главную
галерею, которая демонстрирует возможности анимационного
костра, вращающейся
галактики, падающего
дождя, процедуры
генерации листьев, игры
пятниашки и многое другое. GraphicsJS содержит много других примеров, всеобъемлющей документации и справочник по API.
Основы GraphicsJS
Для того что бы начать использовать библиотеку нужно добваить на ссылку на нее и создать блочный элемент HTML для рисования:<html lang="en">
<head>
<meta charset="utf-8" />
<title>
GraphicsJS Basic Example
</title>
</head>
<body>
<div id="stage-container" style="width: 400px; height: 375px;"></div>
<script src="https://cdn.anychart.com/js/latest/graphics.min.js"></script>
<script>
// GraphicsJS code here
</script>
</body>
</html>
После этого нужно создать стейдж и нарисовать что-нибудь, например прямоугольник или круг или другую фигуру:
// create a stage
varstage
=acgraph
.create('stage-container');
// draw a rectangle
varЗдесь представлен пример CodePen в котором мы идем немного дальше и рисуем символ Дары смерти.stage
.rect(25,50,
350,
300);
Наш Первый Шедевр
Fill, Stroke и текстурная заливка
Любая фигура может быть разукрашена с
использованием fill settings и stroke settings. Любой объект
имеет границу, но только фигуры и закрытые контуры имеют заливку. Настройки
контуров и заливки очень разнообразны, вы можете использовать даже линейный и
круговой градиенты и для контуров и для заливок. Кроме того линии могут быть
прерывистыми, заливка может базироваться на некотором изображении с
использованием наскольких плиточных режимов. Но все это весьма стандартно, что
можно найти и в других библиотеках.Но есть функциональность которая делает GraphicsJS уникальной
библиотекой – это штриховка
и узор заливки, которая позволяет не только использовать доступные 32 вида
штриховок, но также и легко создавать свои новые виды.
Теперь давайте посмотрим как именно это делается!
Мы нарисуем мальенкую картинку с человечком стоящим возле дома, и после этого
улучшим эту картику с помощью различных видов заливки. Для простоты картинку
сделаем немного наивной
(попытаемся не попасть в арт-брют).
// create a stage
varstage
=acgraph
.create('stage-container');
// draw the frame
varframe
=stage
.rect(25,50,
350,
300);
// draw the house
varwalls
=stage
.rect(50,250,
200,
100);
varroof
=stage
.path()
.moveTo(50,
250)
.lineTo(150,
180)
.lineTo(250,
250)
.close();
// draw a man
varhead
=stage
.circle(330,280,
10);
varneck
=stage
.path().moveTo(330,290).lineTo(330,
300);
varkilt
=stage
.triangleUp(330,320,
20);
varrightLeg
=stage
.path().moveTo(320,330).lineTo(320,
340);
varleftLeg
=stage
.path().moveTo(340,330).lineTo(340,
340);
Как вы заметили мы используем переменные – все
методы которые что-то рисуют на стейдже возвращают ссылку на созданный объект,
и эта ссылка может быть использована для изменения или удаления объекта.
Также, обратите внимание на то как формируется
цепочка, которая в GraphicsJS используется повсеместно и помоает сократить код.
Формирование цепочки вызовов (например
stage
.
path
().
moveTo
(320, 330).
lineTo
(320, 340);
) следует использовать
аккуратно, но оно делает код более компактным и легким в понимании.
Теперь давайте эту разукрашку передадим ребенку и
позволим ему ее разукрасить. Потому что даже ребенок способен совладать с
подобной техникой:
// color the picture
// fancy frame
frame
.stroke(["red","green",
"blue"],
2,
"2 2 2");
// brick walls
walls
.fill(acgraph
.hatchFill('horizontalbrick'));
// straw roof
roof
.fill("#e4d96f");
// plaid kilt
kilt
.fill(acgraph
.hatchFill('plaid'));
Здесь показано как наш пример выглядит сейчас.
Далее возмем картику с горцем в килте, котрый
стоит возле каменного замка с соломенной крышей. Мы можем ударится в крайности
и сказать что это действительно произведение искусства, авторские права на
который мы хотим защитить. Давайте это сделаем с кастомным паттерном заливки
постреном в виде текста.
// 169 is a char code of the copyright symbol
vartext
=acgraph
.text().text(String
.fromCharCode(169)).opacity(0.2);
varpattern_font
=stage
.pattern(text
.getBounds());
pattern_font
.addChild(text
);
// fill the whole image with the pattern
frame
.fill(pattern_font
);
Как вы видите это очень просто: создаете
экземпляр текстового
объекта, после формируете паттерн
на стедже и добавляете текст в паттерн.
Создание художественной игры Убийцы-времени за менее чем 50 строк кода
В следующей части статьи, я хочу показать как создать Кликер Печенек – игру на GraphicsJS за
менее чем 50 строк кода.
Название игры “Дворник на ветру” – и игрок
становится дворником в ветренную погоду. В игре используется код с примера
с падающими листьями с галереи GraphicsJS.
Вы можете посмотреть на завершенную игру здесь
(или дочитать до
конца статью).
Слои, zIndex и Виртуальный DOM
Мы начнем с создания стейджа ( как и раньше),
потом объявим несколько переменных:
// create stage
varstage
=acgraph
.create("stage-container");
// color palettes for leaves
varpalette_fill
=['#5f8c3f',
'#cb9226',
'#515523',
'#f2ad33',
'#8b0f01'];
varpalette_stroke
=['#43622c',
'#8e661b',
'#393b19',
'#a97924',
'#610b01'];
// counter
varleavesCounter
=0;
Для этой игры мы будем использовать Слой – объект,
предназначенный для групировки элементов в GraphicsJS. Элементы должны группироваться если вы хотите
применить одни и теже изменения для них, например трансформацию. Вы можете
изменить слои когда находитесь в приостановленном режиме (подробнее об этом
чуть позже), который увеличивает
производительность и пользовательский интерфейс.
В этом демо мы используем функциональность слоев
для того что бы сгруппировать листья и иизбежать их перекрытия метками (которые
показывают, сколько было обработано). Для того что бы это сделать мы создали
метку и после этого вызвали метод
stage
.
layer
,
который привязывает слой к стейджу. Мы присвоили этому слою более низкий zIndex, чем у метки.// create a label to count leaves
varcounterLabel
=stage
.text(10,10,"Swiped: 0",
{
fontSize
:20});
// a layer for the leaves
vargameLayer
=stage
.layer().zIndex(counterLabel
.zIndex()-1);
После этого, нет большой разницы сколько листьев
мы создаем на сслое, они в любом случае не смогут перекрыть метку.
Трансформации
Далее, давайте добавим функциою рисования
листьев. Это позволит нам познакомится с API для трансформаций в GraphicsJS, которое позволяет двигать,
масштабировать, поворачивать и сдвигать и элементы и группы элементов. Когда
трансформации используются со слоями и витруальным DOM – это
становиться очень мощным инструментом.
functiondrawLeaf(
x
,
y
){
// choose a random color from a palette
var
index
=Math
.floor(Math
.random()*
5);
var
fill
=palette_fill
[index
];
var
stroke
=palette_stroke
[index
];
// generate random scaling factor and rotation angle
var
scale
=Math
.round(Math
.random()*
30)
/
10
+
1;
var
angle
=Math
.round(Math
.random()*
360
*
100)
/
100;
// create a new path (leaf)
var
path
=acgraph
.path();
// color and draw a leaf
path
.fill(fill
).stroke(stroke
,1,
'none',
'round',
'round');
var
size
=18;
path
.moveTo(x
,y
)
.curveTo(
x
+size
/2,
y
-size
/2,
x
+3
*
size
/4,
y
+size
/4,
x
+size
,y
)
.curveTo(
x
+3
*
size
/4,
y
+size
/3,
x
+size
/3,
y
+size
/3,
x
,y
);
// apply random transformations
path
.scale(scale
,scale
,x
,y
).rotate(angle
,x
,y
);
return
path
;
};
Вы видите, что любой контур создается одинаковым
образом, но после этого подвергается трансформации. В результате получается
очень интересный рандомный паттерн для листьев.
Обработка событий
Любой объект, стейдж или слой в GraphicsJS может
обрабатывать события. Полный список поддерживаемых событий доступен в EventType API. У стейджа есть четыре
специальные события для контроля отрисовки.
В данном примере мы используем слушатели событий,
которые подсоеденены к объектам листьев. Таким образом исчезают один за одним,
когда пользователь наводит курсор мыши. Для того, что бы этого добиться,
добавте следующий код в конец функции
drawLeaves
перед
вызовом return
.path
.listen("mouseover",function(){
path
.remove();
counterLabel
.text("Swiped: "+
leavesCounter
++);
if
(
gameLayer
.numChildren()<
200)
shakeTree(300);
});
Here we can also see that
we are using the layer to count leaves. if(
gameLayer
.numChildren()<
200)
shakeTree(300);
Обратите внимание, что мы не храним общее
количество листьев. Поскольку листья – это контуры, которые добавляются и
удаляются с конкретного слоя, то это позволяет отслеживать сколько дочерних
элементов он имеет (и сколько листьев осталось).
GraphicsJS предоставляет virtual DOM,абстракцию HTML DOM, легковесную и не
связанную с реализаций SVG\VML конкретного
браузера. Это полезно для того что бы делать много клевых вещей, таких как
отслеживание всех объектов на слое, применения трансформаций для групп и
оптимизации отрисовки с помощью методов, которые позволяют нам отслеживать и
контролировать процесс отрисовки.
Оптимизация производительности
Витруальный DOM вместе с обработчиками событий позволяют пользовтелям GrasphicsJS контролировать
отрисовку. Статья по
производительности может дать вам идею как это можно применять.
При генерации листьев в нашей игре, мы должны
приостановить отрисовку когда добавляем новые листья и возобновить после того
как наши изменения были сделаны.
functionshakeTree(
n
){
stage
.suspend();// suspend rendering
for
(var
i
=0;
i
<n
;i
++){
var
x
=Math
.random()*
stage
.width()/2+
50;
var
y
=Math
.random()*
stage
.height()/2+
50;
gameLayer
.addChild(drawLeaf(x
,y
));// add a leaf
}
stage
.resume();// resume rendering
}
Благодаря такому способу, листья появляются почти
мгновенно.
Наконец, после того как все сделано, вызовем
shakeTree
()
.// shake a tree for the first time
shakeTree(500);
Выводы
Движение к HTML5 изменило веб. Когда речь заходит о современных веб
приложениях или даже о простых сайтах, мы часто сталкиваемся с задачми по
работе с изображениями. Невозможно найти решение которое работает одинаково
хорошо в различных ситуациях, но мы должны присмотреться к GraphicsJS. Это библиотека с отрытым
исходным кодом, быстрая с изумительной поддержкой браузеров и большим
количеством различных возможностей, которые делают ее интересной, удобной и
разумеется полезной.
Я буду рад услышать любые отзывы о библиотеке в
коментариях к статье. Вы используете ее уже? А будете использовать для новых
проектов? Я был бы рад услышать почему да или почему нет. В настоящий момент я
работаю над списком JavaScript библиотек для рисования и статьей, в которой буду сравнивать
их. Поэтому сообщайте мне обо всех библиотеках, которые вы хотите увидеть в
моем обзоре.
Источник: https://www.sitepoint.com/introducing-graphicsjs-a-powerful-lightweight-graphics-library/
Комментариев нет:
Отправить комментарий