В этот части мы разберем анимацию, поработаем с цветом и научимся обрабатывать события.
Предварительно необходимо ознакомиться с первым уроком рисования в HTML 5.
В качестве подопытного, возьму свою птичку из прошлого урока.
Она собрана в объект angrybird из множества элементарных фигур.
var angrybird = new fabric.Group([ tails, light_all_topknot, shadow_body, all_topknot, body, light_body, shadow_all_topknot, belly, all_eye, shadow_group_beak, group_beak ], { });
Каждый объект в Fabric имеет метод animate (наследуя от fabric.Object) который… анимирует этот объект. Давайте поднимем птичку вверх!
Пример:
angrybird.animate({ 'top': 170 },{ onChange: example.renderAll.bind(example) });
Первый аргумент это атрибут который хотим менять. Второй аргумент — финальное значение этого атрибута. Например, если объект находится на высоте 200, и мы указываем «100», то расстояние от верха постепенно изменится с 200 до 100. Последний аргумент — опциональный объект для более детальных настроек (длительность, вызовы, easing, и т.д.) animate имеет очень полезную функциональность — поддержку относительных значений. Например, если нужно подвинуть объект на 100px вправо, то сделать это очень просто:
angrybird.animate('left', '+=100', { onChange: example.renderAll.bind(example) });
3-й аргумент не опциональный, это перерисовка экрана нужна для того чтобы увидеть анимацию.
Опции для анимации:
from: Позволяет менять начальное значение атрибута для анимации (если не хотим использовать текущее).
duration: Длительность анимации. По умолчанию 500 (ms).
onComplete: Функция для вызова в конце анимации.
easing: Функция easing (смягчение).
По умолчанию, animate используют линейную функцию для смягчения анимации. Если такой вариант не подходит, в Fabric имеется большой набор популярных easing функций (доступных через объект fabric.util.ease). Например, вот так можно подвинуть объект направо, при этом отпружинивая в конце:
angrybird.animate('left', 350, { onChange: example.renderAll.bind(example), duration: 1000, easing: fabric.util.ease.easeOutBounce });
Есть и другие популярные функции — easeInCubic, easeOutCubic, easeInElastic, easeOutElastic, easeInBounce, easeOutExpo, и т.д.
ЦветаНезависимо от того, с чем вам удобней работать — hex, RGB, или RGBA форматами цвета — Fabric упрощает утомительные операции и переводы из одного формата в другой. Давайте посмотрим на несколько способов определить цвет в Fabric:
new fabric.Color('#f55'); new fabric.Color('#123123'); new fabric.Color('356735'); new fabric.Color('rgb(100,0,100)'); new fabric.Color('rgba(10, 20, 30, 0.5)');
Перевод формата происходит очень просто. toHex() переводит цвет в hex. toRgb() — в RGB, а toRgba() — в RGB с альфа каналом (прозрачностью).
new fabric.Color('#f55').toRgb(); // "rgb(255,85,85)" new fabric.Color('rgb(100,100,100)').toHex(); // "646464" new fabric.Color('fff').toHex(); // "FFFFFF"
Можно «накладывать» цвета один на другой, или делать из них чёрно-белый вариант.
var redish = new fabric.Color('#f55'); var greenish = new fabric.Color('#5f5'); redish.overlayWith(greenish).toHex(); // "AAAA55" redish.toGrayscale().toHex(); // "A1A1A1"
Ещё более экспрессивный способ работы с цветами — используя градиенты. Градиенты позволяет плавно смешать один цвет с другим, открывая возможность довольно изумительным эффектам.
Fabric поддерживает их с помощью метода setGradientFill, который присутствует на всех объектах. Вызывание setGradientFill это почти как выставление значения «fill» у объекта, только вместо цвета используется градиент.
Поэкспериментируем с птичкой, зальем каждый ее элемент градиентом:
angrybird.setGradientFill({ x1: 0, y1: 0, x2: 0, y2: angrybird.height, colorStops: { 0: '#000', 1: '#fff' } });
результат:
также можем сделать птичку Боба Марли залив 3-х шаговым градиентом, с цветами занимающими по 33% всей длины:
angrybird.setGradientFill({ x1: 0, y1: angrybird.height / 2, x2: angrybird.width, y2: angrybird.height / 2, colorStops: { 0: "green", 0.33: "yellow", 1: "red" } });
результат:
События — незаменимый инструмент для создания сложных приложений. Для удобства пользования, и более детальной настройки, Fabric имеет обширную систему событий; начиная от низкоуровневых событий мыши, и вплоть до высокоуровневых событий объектов.
События позволяют нам «поймать» различные моменты когда что-то происходит на холсте. когда была нажата мышка — cледим за событием «mouse:down». Объект был добавлен на холст — «object:added». Перерисовка холста — «after:render».
API событий очень прост, и похож на то к чему вы скорее всего привыкли в jQuery, Underscore.js, или других популярных JS библиотеках. Есть метод on для инициализации слушателя событий, и есть метод off для его удаления.
var canvas = new fabric.Canvas('...'); canvas.on('mouse:down', function(options) { alert(options.e.clientX + ' ' + options.e.clientY); });
Мы добавили слушатель события «mouse:down» на canvas объекте, и указали обработчика, который будет записывать координаты где произошло это событие. Таким образом, мы можем видеть где именно произошёл клик на холсте. Обработчик событий получает options объект, с двумя параметрами: e — оригинальное событие, и target — Fabric объект на холсте, если он найден. Первый параметр присутствует всегда, а вот target только если клик произошёл на объекте. Ну и конечно же, target передаётся только разработчикам тех событий, где это имеет смысл. Например, для «mouse:down» но не для «after:render» (так как это событие не «имеет» никаких объектов, а просто обозначает что холст был перерисован).
canvas.on('mouse:down', function(options) { if (options.target) { alert('Вы нажали на ' + options.target.type); } });
Этот пример выведет «Вы нажали на (тип объекта)!» если мы нажмём на объект.
События доступны в Fabric. На уровне мышки "mouse:down", "mouse:move", и "mouse:up". Из общих "after:render". Есть события выбора объектов: "before:selection:cleared", "selection:created", "selection:cleared". События объектов: "object:modified", "object:selected", "object:moving", "object:scaling", "object:rotating", и "object:added".
Для удобства, Fabric позволяет добавлять слушатели прямо на Fabric объекты
angrybird.on('selected', function() { alert('Чик-чирик'); });
Пример рисования в canvas при помощи Fabric.js, создание объекта, его анимация и обработка событий.
<html> <head> <title>Angry bird</title> <meta charset="utf-8"/> <script src="min.js"></script> </head> <body> <div style='color:red; margin:auto; width:400px; text-align:center; top:50%;'> <h1>Angry bird</h1> <canvas id="example" width="500" height="500"> Ваш браузер не поддерживает канвас! </canvas> </div> <script> var example = new fabric.Canvas('example'); //хвост var first_tail = new fabric.Triangle({ width: 40, height: 60, fill: '#000', angle: 100, left: 0, top: 0 }); var second_tail = new fabric.Triangle({ width: 30, height: 60, fill: '#000', angle: 140, left: 10, top: -14 }); var third_tail = new fabric.Triangle({ width: 30, height: 60, fill: '#000', angle: 60, left: 10, top: 18 }); var tails = new fabric.Group([ first_tail, second_tail, third_tail ], { left: 40, top: 200 }); //тело var shadow_body = new fabric.Circle({ radius: 156, fill: '#000', left: 201, top: 203 }); var body = new fabric.Circle({ radius: 150, fill: '#FF0050', left: 200, top: 200 }); var light_body = new fabric.Circle({ radius: 146, fill: '#D5002C', left: 198, top: 204 }); //обводка глаз var shadow_lft_eye = new fabric.Circle({ radius: 35, fill: '#000' }); var shadow_rgt_eye = new fabric.Circle({ radius: 29, fill: '#000', left: 60 }); var shadow_group_eye = new fabric.Group([ shadow_lft_eye, shadow_rgt_eye ], { top: 1 }); //глаза var lft_eye = new fabric.Circle({ radius: 30, fill: '#fff' }); var rgt_eye = new fabric.Circle({ radius: 24, fill: '#fff', left: 58 }); var group_eye = new fabric.Group([ lft_eye, rgt_eye ], { }); //зрачки var lft_pupil = new fabric.Circle({ radius: 10, fill: '#000' }); var rgt_pupil = new fabric.Circle({ radius: 7, fill: '#000', left: 40 }); var group_pupil = new fabric.Group([ lft_pupil, rgt_pupil ], { left: 22, top: 1, }); //брови var lft_eyebrow = new fabric.Rect({ width: 26, height: 86, fill: '#000', angle: 114 }); var rgt_eyebrow = new fabric.Rect({ width: 26, height: 86, fill: '#000', left: 68, angle: -114 }); var eyebrows = new fabric.Group([ lft_eyebrow, rgt_eyebrow ], { left: 28, top: -36 }); var all_eye = new fabric.Group([ shadow_group_eye, group_eye, group_pupil, eyebrows ], { left: 250, top: 190, }); //обводка клюва var shadow_top_beak = new fabric.Triangle({ width: 70, height: 110, fill: '#000', top: -2, angle: 114 }); var shadow_bottom_beak = new fabric.Rect({ width: 62, height: 60, fill: '#000', left: -21, top: 8, angle: 45 }); var shadow_group_beak = new fabric.Group([ shadow_top_beak, shadow_bottom_beak ], { left: 288, top: 260 }); //клюв var top_beak = new fabric.Triangle({ width: 60, height: 100, fill: '#FBBA1E', angle: 114 }); var bottom_beak = new fabric.Rect({ width: 52, height: 50, fill: '#FBBA1E', left: -20, top: 8, angle: 45 }); var tt_beak = new fabric.Triangle({ width: 8, height: 106, top: 12, left: -7, fill: '#000', angle: 100 }); var group_beak = new fabric.Group([ bottom_beak, top_beak, tt_beak ], { left: 286, top: 260, }); //пузо var belly = new fabric.Circle({ radius: 100, fill: '#E2C4A8', scaleY: 0.5, left: 200, top: 300 }); //хохолок var topknot = new fabric.Circle({ radius: 60, fill: '#FF0050', scaleY: 0.5, angle: 30 }); var shadow_topknot = new fabric.Circle({ radius: 52, fill: '#D5002C', scaleY: 0.5, angle: 30 }); var topknot2 = new fabric.Circle({ radius: 40, fill: '#FF0050', scaleY: 0.5, left: -60, angle: 20 }); var shadow_topknot2 = new fabric.Circle({ radius: 32, fill: '#D5002C', scaleY: 0.5, left: -60, angle: 20 }); var all_topknot = new fabric.Group([ topknot, topknot2 ], { left: 180, top: 54 }); var shadow_all_topknot = new fabric.Group([ shadow_topknot, shadow_topknot2 ], { left: 172, top: 54 }); var light_topknot = new fabric.Circle({ radius: 64, fill: '#000', scaleY: 0.5, angle: 30 }); var light_topknot2 = new fabric.Circle({ radius: 44, fill: '#000', scaleY: 0.5, left: -60, angle: 20 }); var light_all_topknot = new fabric.Group([ light_topknot, light_topknot2 ], { left: 180, top: 54 }); var angrybird = new fabric.Group([ tails, light_all_topknot, shadow_body, all_topknot, body, light_body, shadow_all_topknot, belly, all_eye, shadow_group_beak, group_beak ], { direction: 1, left: 210 }); var s_ellips = new fabric.Circle({ radius: 100, fill: '#B9BBAD', scaleY: 0.2, left: 230, top: 410 }); example.add( s_ellips, angrybird ); var minScale = 1, maxScale = 1.07; function animate(dir) { angrybird.animate({ scaleX: dir ? maxScale : minScale, scaleY: dir ? maxScale : minScale },{ duration: 1000, onChange: example.renderAll.bind(example) }); angrybird.animate({ 'top': angrybird.getTop() === 200 ? '170' : '200'},{ duration: 1000, onChange: example.renderAll.bind(example) }); s_ellips.animate('radius', s_ellips.getRadiusX() === 130 ? '100' : '130',{ duration: 1000, onChange: example.renderAll.bind(example), onComplete: function() { angrybird.direction = !angrybird.direction; animate(angrybird.direction); } }); } animate(angrybird.direction); angrybird.on('selected', function() { alert('Чик-чирик'); }); </script> </body> </html>
Прикрепленный файл | Размер |
---|---|
Исходная птичка с анимацией | 38.01 кб |