10_10_2 getComputedTiming().currentIterationの利用

10-10 アニメーションタイマーとしての利用」で述べた”2 セットした時間を繰り返し、その回数を教えてくれるタイマー”の例です。ここでは、Animation.effect.getComputedTiming()が返すcurrentIterationを利用します。

ページを開くと、カミナリ小僧がジャンプを始めます。最初は少しだけジャンプしますが、次第に高くジャンプするようになります。

ジャンプ力が増すカミナリ小僧

この例では、ジャンプや落下表現に物理的な計算方法を用いて、<canvas>要素に描画しています。アニメーションタイマーの作成には、duration値に加え、繰り返し回数のiterationsも指定したタイミングパラメータを使用しています。

// 5秒を4回刻むアニメーションタイマー
const timings = {iterations: 4, duration: 5000};
// ターゲットはnull、keyframesはnull
const effect = new KeyframeEffect(null, null, timings);
const animationTimer = new Animation(effect, document.timeline);

また、getComputedTiming()が返すcurrentIterationは、requestAnimationFrame()から呼び出されるアニメーションループで、繰り返し回数に応じたジャンプ力の算出に用いています。

// 今の繰り返し回数を取得(0~3)
currentIteration = animationTimer.effect.getComputedTiming().currentIteration;

// 今の繰り返し回数をジャンプ力に変える。
// 繰り返し回数が増えるほど、ジャンプ力が増す
jumpPower = (currentIteration+1)*(-10);

// <canvas>要素のコンテキストを準備
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.font = '20px century';

// 5秒を4回刻むアニメーションタイマー
const timings = {
    iterations: 4,
    duration: 5000
};
// ターゲットはnull、keyframesはnull
const effect = new KeyframeEffect(null, null, timings);
const animationTimer = new Animation(effect, document.timeline);

// かみなり小僧の最初の位置
const xpos = 140;
let ypos = canvas.height - 84;

const kaminari = new Image();
const cloud = new Image();
// かみなり小僧の画像をロードし、
kaminari.addEventListener('load', () => {
    // キャンバスに描画
    context.drawImage(kaminari, xpos, ypos);
    // 次いで、雲の画像をロード
    cloud.src = "images/cloud.png";
}, false);
kaminari.src = "images/kaminari.png";

// 雲の画像がロードできたら
cloud.addEventListener('load', () => {
    // キャンバスに描画
    context.drawImage(cloud, 120, 10);
    // アニメーションタイマーが準備できたら、
    animationTimer.ready.then(() => {
        // 再生開始 
        animationTimer.play();
        // JavaScriptアニメーションをスタート
        render();
    });
}, false);

// かみなり小僧のジャンプアニメーションに使用する変数
let ay = 0;
let isGoingUp = true;
const friction = 0.9;
const GRAVITY = 2;
let jumpPower = 0;
const ground = canvas.height;
const H = 84; //kaminari.height;
let currentIteration = 0;

const update = () => {
    // ジャンプのパワーを足す
    if (isGoingUp) {
        ay = jumpPower;
    }
    // 落下要因
    ay += GRAVITY;
    // 落下する
    ypos += ay;
    // 着地
    if (ypos > ground - H) {
        // 地面で跳ね返り
        ay *= -1;
        ay *= friction;
        ypos = ground - H;
        // 跳ね返り終わり
        if (Math.abs(ay) < GRAVITY) {
            ay = 0;
            // 今の繰り返し回数を取得(0~3)
            currentIteration = animationTimer.effect.getComputedTiming().currentIteration;
            if (currentIteration === null) {
                currentIteration = 0;
            }
            // 今の繰り返し回数をジャンプ力に変える。
            // 繰り返し回数が増えるほど、ジャンプ力が増す
            jumpPower = (currentIteration + 1) * (-10);
            isGoingUp = true
        }
        // ジャンプしたら後は落下
    }
    else {
        isGoingUp = false;
    }
}

// コンテキストで描画
const draw = () => {
    // キャンバスをクリア
    context.clearRect(0, 0, canvas.width, canvas.height);
    // コンテキストを一時的に保存
    context.save();
    // かみなり小僧を適切な位置に描画
    context.drawImage(kaminari, xpos, ypos);
    // 雲を決まった位置に描画
    context.drawImage(cloud, 120, 10);
    // キャンバスの左上に、今の繰り返し回数とジャンプ力を描画
    context.fillText(currentIteration, 27, 30);
    context.fillText(jumpPower, 10, 50);
    // コンテキストを回復
    context.restore();
}

const render = () => {
    update();
    draw();
    window.requestAnimationFrame(render);
}

コメントを残す

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

CAPTCHA