4_3:応答:イージングの導入 p5.js JavaScript

Webアニメーションでは、ある位置からある位置に移動するとき、目的地にすぐにではなく少し間をとってから到達したり、だんだん速くなったり(加速)、だんだん遅くなったり(減速)するものがよく見られます。これはイージングと呼ばれるテクニックで、アニメーションに加速度の増減要因を設定することで、だんだん速くなったり遅くなったりして目的地に到達する効果が生まれます。

イージングは元々Flash開発者のRobert Pennerが考案したもので、イージング関数と呼ばれる、数学を駆使した関数で実現されます。イージング関数に関する詳細は、当サイトの「11-1 そもそもイージング関数は一体何を…」で触れています。

しかしイージング関数を使わなくても、目的地に近づくにつれてだんだん遅くなるx軸方向へのアニメーションは、次の要領で作成できます。

  1. 移動スピードを距離の何分の1にするかを表す数値easing(0から1までの小数)を決める
  2. 行先targetXposを決める
  3. 描画物から行先までの距離dxを計算する
  4. 距離に、距離の何分の1にするかを表すeasingを掛け、スピードvxを求める
  5. スピードを現在位置xposに加算する
  6. 3,4,5を繰り返す

easingを0.5、targetXposを800、xposを0とした場合、開始から3フレームめまでの計算は下図のように表せます。

コードは次のように記述できます。

// 描く円の現在位置
let xpos = 0;
const targetXpos = 800;
// イージングの値:0から1の間の数値
// 距離の何分の1かを表す
const easing = 0.5;

function setup() {
    createCanvas(820, 120);
    background(204);
}

function draw() {
    // 残りの距離
    const dx = targetXpos - xpos;
    // 速度は残りの距離に、距離の何分の1かを掛けたもの
    const vx = dx * easing;
    // 新しい現在位置は、前の現在位置に速度を足したもの
    xpos = xpos + vx;

    print('dx : ' + dx);
    print('vx : ' + vx);
    print('xpos : ' + xpos);

    ellipse(xpos, 60, 10, 10);
}

下図はこの実行結果です。xposは0からスタートして、draw()の1フレームめで400となり、円は(400, 60)の位置に描かれます。xposは2フレームめで600となり、円は(600,60)の位置に描かれます。円と円の距離が右に進むほど小さくなっているのは、スピードが遅くなっている(だんだん遅くなっている)ことを示しています。

plotly.jsなどのJavaScriptライブラリを使用すると、xposの変化の具合がグラフの曲線で確認できます。plotly.jsの使い方は当サイトの「3-3 基本 その3 視覚化」で触れています。

if (frameCount < 12) {
    plot(frameCount, targetXpos, frameCount, xpos, easing);
}

下図はeasingを0.2に設定したときの結果です。

新体操のリボンのような線

イージングのテクニックを線の連続描画に応用した例です。マウスポインタの動きに少し遅れて線が描かれます。

let xpos = 0;
let ypos = 0;
let px = 0;
let py = 0;
const easing = 0.05;

function setup() {
    createCanvas(480, 120);
    stroke(218, 37, 182, 102);
    background(204);
}

function draw() {
    const targetX = mouseX;
    const dx = targetX - xpos;
    const vx = dx * easing;
    xpos = xpos + vx;

    const targetY = mouseY;
    const dy = targetY - ypos;
    const vy = dy * easing;
    ypos = ypos + vy;

    const weight = dist(xpos, ypos, px, py);
    strokeWeight(weight);
    line(xpos, ypos, px, py);
    px = xpos;
    py = ypos;
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA