html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Mother of the gods, it is Surfingbird!

You finally got here. We've been waiting for you and we have so many interesting things!

Close

Анимация и Canvas из песочницы

Добрались руки мои до Canvas. Посматривал я на него давненько, очень уж он мне в качестве инструмента для графиков приглянулся. Да и неделя Canvas на Хабре поддержала интерес.

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

Канва


Тут все просто и стандартно.
<!DOCTYPE html>
<html>
  <head>
    <title>Animation test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>    
    <canvas id="cnv" width="600" height="200">It's not working!</canvas>
    <select id="animations" name="animations" onchange="changeAnimation(this.value)">
      <option value="stop">Stop</option>
      <option value="jump">Jump</option>
      <option value="bum">Bum</option>
      <option value="dead">Dead</option>
    </select>
  </body>
</html>

* This source code was highlighted with Source Code Highlighter.


Под холстом добавлен Select со списком анимаций для объекта. Объект у меня будет один, хотя алгоритм не подразумевает каких либо ограничений.

Глобальные переменные

Теперь перейдем к JS. Здесь мне понадобятся несколько переменных для хранения объектов сцены и возможных анимаций.
//Сократим запись для потомков
function $(id) {
  return document.getElementById(id);
}
      
var сtx     = $('cnv').getContext('2d'); //Наша канва
var childs  = {};                        //Массив объектов сцены
var animate = {};                        //Массив анимаций для объектов

* This source code was highlighted with Source Code Highlighter.



В childs будут храниться все объекты сцены с базовыми параметрами. Мы будем пробегаться по массиву и отрисовывать один за другим.
В animate храним для объекта его анимации. Тут можно сделать и по-другому, к примеру в animate храним анимации только для объектов которым они нужны, а для прочих храним информацию по отрисовке в самом массиве childs. В моем варианте каждый объект должен иметь по меньшей мере одну анимацию, если хочет быть отображенным на холсте.

Заполняем массивы

Сначала добавим наш объект. Я не стал росписывать параметры, т.к. считаю что для краткости кода можно на этой пойти, да и имена все интуитивно понятные.

function initAnimation() {       

  //Добавляем шарик
  childs['ball'] = {
    'at' : 'jump', //Стартовая анимация
    'w'  : 30,   //Ширина объекта
    'h'  : 30,   //Высота объекта
    'fw' : 30,   //Ширина кадра анимации
    'x'  : 100,  //Положение по горизонтали
    'y'  : 100   //Положение по вертикали
  }

  //Добавляем в массив анимации для шарика
  animate['ball'] = {
    'jump': {                      //Ключ есть имя анимации
      'el'    : null,              //Объект Image
      'src'   : 'images/ball.png', //Путь к изображению
      'step'  : 0,                 //Текущий шаг анимации
      'speed' : 3,                 //Скорость анимации
      'curr'  : 0,                 //Счетчик кадров
      'steps' : 3,                 //Количество кадров анимации, считаем от 0
      'onend' : null               //Функция для вызова по окончании анмации
    },
    'bum': {
      'el'    : null,
      'src'   : 'images/ball_m.png',
      'step'  : 0,
      'speed' : 3,
      'curr'  : 0,
      'steps' : 7,
      'onend' : 'onBumEnd'
    },
    'stop': {
      'el'    : null,
      'src'   : 'images/ball_s.png',
      'step'  : 0,
      'speed' : 10,
      'curr'  : 0,
      'steps' : 0,
      'onend' : null
    },
    'dead': {
      'el'    : null,
      'src'   : 'images/ball_d.png',
      'step'  : 0,
      'speed' : 10,
      'curr'  : 0,
      'steps' : 0,
      'onend' : null
    }
  }

  //Идем по всем объектам
  for (var o in childs) {          

    //И по все их анимациям
    for (var a in animate[o]) {

      //Подгружаем изображения
      var img = new Image();
      img.src = animate[o][a].src;
      //Помещаем объект изобраения в анимацию
      animate[o][a].el = img;

    }

  }

}

* This source code was highlighted with Source Code Highlighter.



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

Изображение представляет собой следующее:
image
Это самое большое изображение, ответственное за самую длинную анимацию «Bum» в 8 кадров.

Speed и curr отвечают за скорость переключения кадров. Я перерисовываю холст каждые 16мс и чтобы кадры сменялись с требуемой скоростью я считаю curr и по достижении speed меняю кадр.

Onend я вызываю по окончании анимации. Здесь мы можем сменить тип анимации — со взрыва на отображение останков или удалить объект из массива. Для этого чуть выше у меня есть функция:
function onBumEnd() {
        
  //Меняем тип анимации на мертый шарик
  childs['ball'].at = 'dead';
  //Сбрасываем счетчик
  animate['ball'][childs['ball'].at].curr = 0;
        
}


* This source code was highlighted with Source Code Highlighter.



Анимации

Для объекта есть 4 анимации:
  • Стоит: stop
  • Прыгает: jump
  • Взрывается: bum
  • Мертв: dead


Функция для смены анимации

Чтобы удобно менять анимации у нас есть Select и функция для него:
function changeAnimation(value) {
        
  //Меняем анимацю на выбранную
  childs['ball'].at = value; 
  //Сбрасываем счетчик      
  animate['ball'][childs['ball'].at].curr = 0;
        
}


* This source code was highlighted with Source Code Highlighter.


Запускаем

Вот и готовы все изображения и массивы, и я запускаю анимацию.
function startAnimation() {

  //Запускаем единый таймер
  setInterval(function() {          

    //Чистим сцену
    ctx.save();
    ctx.fillStyle = '#FFFFFF';
    ctx.fillRect(0, 0, 600, 200);
    ctx.restore();

    //Проходим по всем объектам и отрисовываем
    for (var o in childs) {

      //Смотрим текущую анимацию
      if (animate[o]) {
        
        //Берем текущий шаг
        var step = animate[o][childs[o].at].step;

        //Рисуем его
        ctx.drawImage(
          animate[o][childs[o].at].el,     //Объект Image анимации
          Math.round(childs[o].fw * step), //Берем текущий кадр, ширина кадра * шаг
          0,                               //Кадры идут один за другим, тут 0
          childs[o].w,                     //Вырез в ширину объекта
          childs[o].h,                     //И в высоту
          childs[o].x,                     //Размещаем по горизонтали на холсте
          childs[o].y,                     //И по вертикали
          childs[o].w,                     //Ширина как у кадра
          childs[o].h                      //Ну и высота
        );
        
        //Проверяем счетчик и если достигли speed, переходим к следующему кадру
        if (animate[o][childs[o].at].curr >= animate[o][childs[o].at].speed) {

          //Проверяем, если кадр последний переходим к первому
          if (animate[o][childs[o].at].step >= animate[o][childs[o].at].steps) {

            animate[o][childs[o].at].step = 0;

            //Кадр последний, значит вызываем функцию, если есть
            if (animate[o][childs[o].at].onend)
              window[animate[o][childs[o].at].onend]();

          }
          else animate[o][childs[o].at].step++;

          //Сбрасываем счетчик
          animate[o][childs[o].at].curr = 0;

        }

        //Увеличиваем счетчик
        animate[o][childs[o].at].curr++;      

      }

    }

  }, 1000/16);

}


* This source code was highlighted with Source Code Highlighter.



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

Код целиком

Посмотреть можно здесь.
Скачать можно здесь.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

4

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • skypractic
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции