Как анимировать графики полотна (HTML)

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. В случае разработки приложений для Windows 10 см. раздел последняя документация]

Элемент полотна — это доступная для рисования область документа HTML, на которой средствами JavaScript можно создавать графические объекты, такие как анимации, диаграммы и игры. В этом разделе приводится описание действий, которые необходимо выполнить, чтобы анимировать простой рисунок с помощью элемента полотна. Эти сведения помогут вам приступить к работе.

Необходимые условия

В этом разделе предполагается, что вы:

  • Умеете создавать простые приложения Магазина Windows на JavaScript с помощью шаблона из библиотеки Windows для JavaScript.
  • Имеете общее представление о HTML и JavaScript.

Инструкции по созданию первого приложения Магазина Windows на JavaScript см. в разделе Создание первого приложения Магазина Windows на JavaScript. Инструкции по использованию шаблона WinJS см. в разделе "Получение и использование набора средств WinJS".

Инструкции

Этап 1: Настройка времени анимации

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

requestAnimationFrame(animationFunction);

Метод requestAnimationFrame учитывает видимость страницы и частоту обновления экрана для определения числа кадров в секунду, которые необходимо выделить для анимации (то есть вызова animationFunction).

В нашем примере на JavaScript выполняется рисование анимированной окружности, вращающейся по спирали вдоль окружности большего радиуса.

requestAnimationFrame(draw);

Анимация представлена ниже (результаты могут отличаться, более быстрое оборудование приводит к окружностям с меньшим шагом).

Пример вращающейся по спирали окружности, полученной путем анимации полотна.

Этап 2: Рисование изображения

  1. Очистка полотна

    Перед рисованием каждого из кадров вам необходимо будет очищать полотно.

    Существуют различные методы очистки полотна или фрагментов изображения, например очистка определенных областей с помощью свойства globalCompositOperation или посредством контуров обрезки с применением метода clip. Самым простым способом очистки полотна является применение метода clearRect.

    В нашем примере метод clearRect используется для очистки всего полотна, но чтобы легче можно было увидеть эффекты при рисовании нашего изображения, метод clearRect закомментирован. Если бы эта строка кода была раскомментирована, вы бы увидели одиночную окружность, вращающуюся по спирали внутри другой окружности большего диаметра, при этом перед прорисовкой каждого кадра ее след очищался бы.

    // The clearRect method clears the entire canvas.
    context.clearRect(0, 0, 160, 160);
    
  2. Сохранение состояния полотна

    Во время рисования изображения вы можете внести изменения в некоторые параметры, такие как стили или преобразования. Если в начале каждой повторной прорисовки изображения вы хотите использовать исходные параметры, то можно воспользоваться методом save.

    Методы save и restore применяются для сохранения состояния полотна в стеке и возвращения прежнего состояния полотна. Состояние полотна включает в себя все стили и преобразования, которые были применены. Каждый раз при вызове метода save текущее состояние полотна сохраняется в стеке. Метод restore возвращает последнее сохраненное состояние из стека.

    В нашем примере метод save используется непосредственно перед тем, как установить некоторые преобразования, для прорисовки и передвижения анимированной окружности.

    // Save the canvas state.
    context.save();
    
  3. Рисование изображения

    Во время рисования изображения на полотне для внесения в него изменений вы можете использовать два вида преобразования: методы "Перевести" и "Повернуть".

    Метод "Перевести" используется для перемещения полотна и его источника в другую точку сетки полотна:

    translate(x, y)
    

    Метод имеет два аргумента: x — число единиц, на которое полотно перемещается влево или вправо, и y — число единиц, на которое полотно перемещается вверх или вниз.

    Рекомендуется сохранять состояние полотна перед выполнением каких-либо преобразований, поскольку легче вызвать метод restore, чем делать обратный перевод для возврата полотна в первоначальное состояние. Метод translate позволяет разместить изображение в любом месте полотна без настройки координат вручную.

    Метод rotate применяется для вращения полотна вокруг текущего источника. Данный метод имеет всего один параметр — угол (в радианах), на который поворачивается полотно.

    rotate(angle)
    

    Вращение происходит по часовой стрелке, при этом центральная точка вращения всегда является источником полотна (верхний левый угол). Чтобы переместить центральную точку, необходимо переместить полотно с помощью метода translate.

    В нашем примере мы будем чередовать вызовы методов translate и rotate. Первый вызов метода translate отцентрирует анимацию на полотне.

    Далее мы осуществим в два подхода вызовы методов rotate и translate. Первый вызов методов rotate и translate даст в результате маленькую окружность, движущуюся по полотну вдоль окружности большого радиуса. При втором вызове методов появится небольшая окружность, движущаяся вдоль окружности намного меньшего радиуса.

    Размеры полотна установлены следующие: 160 пикселей в высоту и 160 пикселей в ширину. Поэтому для метода "Перевести" мы устанавливаем координаты x и y равными 80, получая таким образом размещение всей анимации по центру полотна.

    // centers the image on the canvas             
    context.translate(80, 80);
    

    Первый вызов метода rotate мы начинаем с использования объекта date, чтобы вычислить параметр метода rotate. Данным параметром является угол поворота полотна.

    var time = new Date();
    context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
    

    Примечание. Значение, использованное для расчета параметра getSeconds, равно 60, а значение, использованное для расчета параметра getMilliseconds, равно 60 000.

    Метод translate перемещает координату х, что перемещает вращающуюся окружность вокруг полотна по орбите большего радиуса.

    // Translate determines the size of the circle's orbit.
    context.translate(50, 0);
    

    В результате первого вызова методов rotate и translate появляется следующее.

    Большая окружность без циклов вращения.

    Следующие два вызова методов rotate и translate создают орбиту меньшего радиуса, образующую циклы вращения.

    // Rotate causes the circle to move in a small orbit.
    context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
    
    // Translate determines the size of the orbit.
    context.translate(0, 5);
    

    Примечание. При вычислении угла для второго вызова метода поворота значение, использованное для расчета параметра getSeconds, равно 6, а значение, использованное для расчета параметра getMilliseconds, равно 6 000.

    Если первые методы rotate и translate закомментировать, то при повторном вызове методов rotate и translate будет нарисовано следующее.

    Окружность, образующая циклы вращения.

    После того как все изменения положения будут выполнены, на полотне будет нарисована окружность.

    // This draws the repositioned circle
    context.beginPath();
    context.arc(5, 5, 4, 0, Math.PI*2, true); 
    context.stroke();
    
  4. Восстановление состояния полотна

    Ранее на шаге b мы сохранили состояние полотна, так что теперь мы сбросим это значение, чтобы нарисовать следующий кадр.

    // Restores the canvas to the previous state
    context.restore();
    

Полные примеры

Анимированная графика

В этом примере на JavaScript выполняется рисование анимированной окружности, вращающейся по спирали вдоль окружности большего радиуса.

window.onload = init;
  
// As an optimization, make "context" a global variable that is only set once.
var context;
  
function init(){
  context = document.getElementById('canvas').getContext('2d');    
  window.requestAnimationFrame(draw);
} // init

function draw() {
  // Save the canvas state.
  context.save();         
  
  // context.clearRect(0, 0, 160, 160);

  // centers the image on the canvas             
  context.translate(80, 80); 
  
  // Rotate moves the spiraling circle around the canvas in a large orbit.
  var time = new Date();
  context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  
  // Translate determines the location of the small circle.
  context.translate(50, 0);  
  
  // Rotate causes the circle to spiral as it circles around the canvas.
  context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  
  // determines the size of the loop
  context.translate(0, 5);  
  
  // This draws the circle
  context.beginPath();
  context.arc(5, 5, 4, 0, Math.PI*2, true); 
  context.stroke();
  
  // Restores the canvas to the previous state
  context.restore();
  window.requestAnimationFrame(draw);
}  // draw

Это пример каскадных таблиц стилей (CSS), в котором создается черная граница вокруг элемента полотна.

/* style the canvas element with a black border. */
canvas { border: 1px solid black; }

Этот HTML-файл создает элемент полотна и использует внешние файлы JavaScript и CSS.

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="myJavascript.js"></script>
        <link Rel="stylesheet" Href="myStyle.css" Type="text/css">
    </head>
    <body>
        <canvas id="canvas" width="160" height="160" />
    </body>
</html>

Связанные разделы

Краткое руководство. Рисование на полотне