С новым годом! И немного анимации с помощью HTML5 Canvas.
Хочу привести простой пример использования возможностей рисования и анимации с помощью HTML5. Собственно, то, что получится в итоге, вы можете наблюдать чуть выше (разумеется, если вы не отключили JavaScript). Для того, что бы получить такой результат - будем использовать элемент canvas, который включен в спецификацию HTML5, и предназначен для рисования.
Первым делом нужно создать страницу и поместить на нее элемент canvas:
<!DOCTYPE html> <html> <body> <canvas id="myCanvas" width="200" height="200"></canvas> <script> </script> </body> </html>
По умолчанию, размер области для рисования элемента canvas - 300px x 150px. Поскольку нам хватит и меньше - задаем размер 200px x 200px. Теперь нужно написать скрипт, который будет рисовать нашу новогоднюю елку. Соответственно, весь дальнейший код добавим в тег <script> на только что созданной странице. Начнем с рисования самой елки:
var colorShift = 0; //рисуем елку function drawTree() { var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); //рисуем листву и нижнюю часть ctx.fillStyle = "green"; ctx.fillRect(60, 50, 40, 90); ctx.fillRect(40, 110, 80, 40); a = 60; b = 10; for (var i = 0; i < 4; i++) { drawLeaf(-20 + a - (i * 10), b + (i * 30), ctx, "left"); drawLeaf(20 + a + (i * 10), b + (i * 30), ctx, "right"); } ctx.fillStyle = "brown"; ctx.fillRect(70, 150, 20, 20); drawCircles(ctx); drawText(ctx); } //нарисовать листву function drawLeaf(x, y, ctx, style) { ctx.beginPath(); ctx.fillStyle = "green"; if (style == "right") { ctx.moveTo(x, y); ctx.lineTo(x + 40, y + 40); ctx.lineTo(x, y + 40); } else { ctx.moveTo(x + 40, y); ctx.lineTo(x, y + 40); ctx.lineTo(x + 40, y + 40); } ctx.fill(); } //текст на елке function drawText(ctx){ ctx.font="19px Impact"; ctx.fillStyle = 'gold'; ctx.fillText("2015",61,90); } function drawCircles(ctx) { var radius = 3; drawCircle(90,50,radius, getColor1(),ctx); drawCircle(80,30,radius,getColor2(),ctx); drawCircle(70,60,radius,getColor3(),ctx); drawCircle(90,65,radius,getColor4(),ctx); drawCircle(70,100,radius,getColor5(),ctx); drawCircle(95,110,radius,getColor4(),ctx); drawCircle(80,120,radius,getColor3(),ctx); drawCircle(110,120,radius,getColor2(),ctx); drawCircle(95,135,radius,getColor1(),ctx); drawCircle(49,110,radius,getColor5(),ctx); drawCircle(60,120,radius,getColor3(),ctx); drawCircle(60,135,radius,getColor2(),ctx); } function drawCircle(x,y,radius,color,context){ context.beginPath(); context.arc(x, y, radius, 0, 2 * Math.PI, false); context.fillStyle = color; context.fill(); context.lineWidth = 1; context.strokeStyle = color; context.stroke(); }
Функция drawTree предназначена для рисования всего рисунка, то есть всей елки. Функция drawLeaf - для рисования ветвей, а функции drawCircles и drawCircle - для рисования кругов на елке, которые будут являться "гирляндой" на нашей елке. Функция drawText рисует текст "2015". Функции getColor1(), getColor2() ... - это функции получения цвета каждого элемента "гирлянды", которые мы скоро добавим. Переменная colorShift нужна для обеспечения анимации, которую мы тоже сейчас добавим.
function getColor1(){ return "rgba("+colorShift+", 90,50, 1)"; } function getColor2(){ return "rgba(100,"+colorShift+",150, 1)"; } function getColor3(){ return "rgba(155, 200, "+colorShift+", 1)"; } function getColor4(){ return "rgba("+colorShift+", 100,200, 1)"; } function getColor5(){ return "rgba("+colorShift+", 90,10, 1)"; }
Напишем несколько функций, которые возвращают различные значения цвета, эти цвета мы будем использовать для элементов "гирлянды". В каждой из функций, зададим значение цвета в формате RGBA, причем один из компонетов цвета будет задаваться с помощью переменной colorShift, которая будет изменяться в процессе анимации. Таким образом, получится плавное псевдослучайное изменение цвета каждого элемента "гирлянды". Наша елка почти готова, осталось добавить саму анимацию, с помощью которой мы создадим нечто похожее на гирлянду, которая плавно переливается разными цветами:
function animate() { reqAnimFrame = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame; reqAnimFrame(animate); colorShift = colorShift + 1; if (colorShift == 255){ colorShift = 0; } drawTree(); } animate();
Теперь самое интересное - анимация. Для этого будем использвать функцию RequestAnimationFrame. Логично, что для обеспечения анимации нужно перерисовывать изображение. Для этого можно воспользоваться функцией SetInterval (SetTimeout), однако сейчас рекомендуется использовать функцию RequestAnimationFrame.
Во-первых, SetTimeout не принимает во внимание то, что еще происходит в браузере. Страница может, например, находится в неактивной вкладке браузера. При этом она будет использовать ресурсы процессора не взирая на это.
Кстати умный Chrome делает setInterval и setTimeout равным 1fps в скрытых вкладках.. но, насколько я знаю, так пока делает только chrome.
Во-вторых, SetTimeout требует перерисовки страницы не в то же время, когда это делает ваш компьютер (а он делает это регулярно). Это означает, что ваш бедный браузер должен синхронизировать вашу горе-анимацию с обновлением всего экрана, и если ее частота не синхронизирована с обновлением всего экрана, это может потребовать больше вычислительной мощности. А это загрузка процессора, нагрев, шум куллера, расход батареи мобильных девайсов.. и т.п
Чтобы преодолеть эти проблемы, Mozilla (создатели Firefox) предложил функцию requestAnimationFrame, которая впоследствии была принята и усовершенствована командой WebKit (Chrome и Safari). Она обеспечивает встроеный API для запуска любых типов анимации в браузере (DOM элементов, canvas, WebGL и др.) [*]
В функции animate используем одну из версий функции RequestAnimationFrame, в зависимости от того, какой браузер используется. И при каждом вызове изменяем значение переменной colorShift, с помощью чего обеспечивется изменение цвета "гирлянды".
Теги: html5 web javascript
comments powered by Disqus