MENU

JavaScript関数・メソッド画像処理

【JavaScript】 DOMのanimateメソッドでアニメーションしてみる

更新日:2021/09/09

 

DOM要素のanimateメソッドを使用すると、CSSの@keyframesと同じような感覚で要素のアニメーションを制御できます。
jQueryにも同名のメソッドがありますが、今回はWeb Animations API のメソッドについて紹介します。

 

animateメソッドの概要

 

まずは次のデモを見てください。

 

 

デモ

 

 

 

これは次のようなDOM要素とCSSで構成されています。

 

 

HTML

 


<div id="demo1" style="height: 100px;width: 100px;border: 1px solid black;"></div>

 

CSS

 


#demo1{
    animation: anime infinite 10s linear;
}
@keyframes anime {
    0% {
        background-color : #fff;
        border-radius :  0 ;
        margin-left : 0;
    }
    50% {
        background-color : #000;
        border-radius :  50px ;
        margin-left : 300px;
    }
    100% {
        background-color : #fff;
        border-radius :  0 ;
        margin-left : 0;
    }
}

 

 

上のデモの欠点は、ブラウザがアニメーション動作の開始を決定しているということです。
つまり、任意のタイミングで開始や停止がおこなえません。

 

animateメソッドを使用することで、このようなアニメーションの動作を制御することができます。

animateメソッドの使用例

 

前項のデモをanimateメソッドに置き換えてみます。

 

次のコードは、スタイルの変化を配列で渡しています。

 


window.addEventListener( "DOMContentLoaded" , ()=>{

    const div = document.getElementById("demo");
    div.animate( {
            backgroundColor : ["#fff","#000","#fff" ],
            borderRadius : [ "0" , "50px"  , "0" ],
            marginLeft : [ "0" , "300px", "0" ],
        } , {
            duration: 10000,
            iterations: Infinity
        });
});

 

CSSと同じような形式で、キーフレームを渡すことも可能です。

 


window.addEventListener( "DOMContentLoaded" , ()=>{

    const div = document.getElementById("demo");
    div.animate( [ {
            backgroundColor : "#fff",
            borderRadius : "0",
            marginLeft :  "0" ,
        } , {
            backgroundColor :"#000",
            borderRadius :  "50px" ,
            marginLeft :  "300px",
        }  ,{
            backgroundColor :"#fff" ,
            borderRadius :  "0" ,
            marginLeft : "0" ,
        }  ] , {
            duration: 10000,
            iterations: Infinity
        } );

});

 

animateメソッドの構文

 

animateは、DOM要素からアクセスできるメソッドです。

 

次のような構文で、二つの引数を受け付けます。

 

 

要素.animate( キーフレーム , タイミング );

 

 

引数の値の一部は、CSSのプロパティ名を指定します。
"-"が含まれるプロパティ名は、"-"を取り除き、続く一文字を大文字で表記するキャメルケースで記述します。

 

例:
background-color → backgroundColor

 

引数1:キーフレーム

 

一番目の引数は、変化させたいCSSスタイルを列挙します。

 

列挙方法は、次の二つの方法があります。

 

 

スタイル値を配列で指定

 

変化させたいスタイルをプロパティ名としたオブジェクトを指定します。
各プロパティの値は、変化させたい値を順番に並べた配列です。

 

指定例

 


{
        backgroundColor : ["#fff","#000","#f00"],
        borderRadius : [ "0" , "50px" , "0" ],
        marginLeft : [ "0" , "300px" , "0" ],
        offset: [ 0, 0.5 ] // 後述
        easing: [ "linear", "ease-in-out" ] // 後述
}

 

配列の要素は、一番目の値が0%で最後が100%に相当します。
それ以外の値は等間隔で割り振られます。

 

また、各々の要素数を同じにする必要はありません。

 

各々の要素数で間隔が決まる

 


{
        backgroundColor : ["#fff","#000","#f00"], // 0% , 50% , 100%
        borderRadius : [ "0" ,  "0" ],  // 0% , 100%
        marginLeft : [ "0" , "300px" , "300px" , "0" ], // 0% , 33% , 66% , 100%
}

 

間隔を自分で制御したいときは、offsetプロパティを使用できます。

 

offsetは、0から1までの小数で指定します。
0が0%、1が100%に相当します。

 

offset指定例

 


{
        backgroundColor : ["#fff","#000","#f00"], // 0% , 20% , 100%
        offset: [ 0, 0.2 ] 
}

 

 

easingプロパティは、「最初はゆっくりで後半は速く」などといった、アニメーション動作の動きを指定できます。

 

easing指定例

 


{
        backgroundColor : ["#fff","#000","#f00"], // 0% , 20% , 100%
         easing: [ "linear", "ease-in-out" ]
}

 

easingプロパティは次の値を指定できます。

 

easingプロパティの値
意味
"linear"一定の速度で変化
"ease"最初は速く後半は減速
"ease-in"最初は遅く後半は加速
"ease-in-out"最初は遅く中盤加速後半は減速
"ease-out"最初は速く後半は減速。最初はeaseよりも少し速い
"step-start"最初に100%の状態に変化
"step-end"0%の状態を維持し、最後に100%の状態に変化
"cubic-bezier( 引数1 , 引数2 , 引数3 , 引数4)"4つの引数で変化をカスタマイズする
"steps( 引数1 , 引数2 )"2つの引数で変化をカスタマイズする

 

具体的な変化については、次のツールで確認できます。
css/javascript イージング確認ツール

 

スタイルの組を配列で指定

 

スタイル値を組み合わせたオブジェクトを、順番に並べた配列です。

 

こちらも方法でも、offseteasing指定が可能です。

 


    [
        {
            backgroundColor : "#fff",
            borderRadius :  "0" ,
            marginLeft : "0",
            offset: 0,
            easing : "linear" ,
        },
        {
            backgroundColor : "#000",
            borderRadius :  "50px" ,
            marginLeft : "300px",
            offset: 0.5,
            easing : "ease-in-out" ,
        },
        {
            backgroundColor : "#f00",
            borderRadius :  "0" ,
            marginLeft : "0" ,
        },
    ]

 

 

引数2:タイミング

 

animateメソッドの2番目の引数は、再生時間などを指定します。
この値はミリ秒を表す整数値、またはオブジェクトです。

 

次の2つの例は、共に5秒のアニメーションを実行しています。

 

ミリ秒で指定

 


div.animate( { backgroundColor : ["#fff","#000","#f00"] } , 5000 );

 

オブジェクトで指定

 


div.animate( { backgroundColor : ["#fff","#000","#f00"] } , { duration : 5000 } );

 

オブジェクトで指定した場合、次のようなプロパティを使用できます。

 

プロパティ名意味
duration再生時間(ミリ秒)ミリ秒
delay再生開始までの待機時間(ミリ秒)ミリ秒(規定値は0)
direction再生方向"normal" :

0%から100%へ変化
"reverse" :
100%から0%へ変化
"alternate" :
0%から100%→100%から0%の繰り返し
"alternate-reverse" :
"alternate"の逆パターン
規定値:"normal"

easingアニメーション動作の変化率easingプロパティの値参照
endDelay再生終了後の待機時間ミリ秒(規定値は0)
fillアニメーション前後の状態"none" :

delay中を含めてcssのみ適用
"forwards" :
終了時の状態を維持
"backwards" :
delay中からアニメーション開始時の状態を反映
"both" :
"forwards""backwards"の両方
規定値:"none"

iterationStart再生開始のタイミング。

0.2とした場合、20%から100%の次に
0%から20%まで再生される

0以上の小数(規定値は0)
iterations再生回数0以上の小数(規定値は1)

Infinityを指定すると、無限ループする

idアニメーションを識別するためのID文字列で指定
compositeCSSなどの元となる状態と

アニメーションの現在の状態との処理方法

"replace" :
アニメーションの現在の状態で置き換え
"add" :
元となる状態にアニメーションの状態を追加
"accumulate" :
元となる状態にアニメーションの状態を累積
規定値:"replace"

iterationComposite繰り返し時の状態の取り扱い方法"replace" :

現在の状態で置き換え
"accumulate" :
これまでの状態を累積
規定値:"replace"

Animationのメソッド

 

animeteメソッドを実行すると、戻り値としてAnimationオブジェクトを受け取ることができます。

 

このオブジェクトを使用することで、アニメーションの一時停止や再開などをおこなえます。

 

Animationオブジェクトメソッドの使用例

 

デモ

 

 

 

 

html

 


<div id="demo2" style="height: 100px;width: 100px;border: 1px solid black;"></div>

<button id="stop">停止</button><button id="pause">一時停止</button>
<button id="play1">再生</button><button id="play2">2倍速</button>
<button id="play10">10倍速</button><button id="play5s">5秒後再生</button><span id="wait"></span>

 

css

 

#demo2{ background-color: red;}
button{ margin:10px;}

 

JavaScript

 


window.addEventListener( "DOMContentLoaded" , ()=>{

    const div = document.getElementById("demo2");
    const anime = div.animate( {
            backgroundColor : ["#fff","#000" ,"#fff"],
            borderRadius : [ "0" , "50px" , "0" ],
            marginLeft : [ "0" , "300px" , "0"],
        }, {
            duration: 30000,
            iterations: Infinity,
            composite:"add",
        });
    anime.cancel();

    const isRunning = ()=>anime.playState === "running";
    const isFunction = func=>typeof func === "function";

    const buttonDisabled = flg => buttons.forEach( b => b.disabled = flg );
    const readyWait = ( func = null)=>{
        buttonDisabled(true);
        anime.ready.then( isFunction( func ) ? func : ()=>buttonDisabled( false ));
    };
    const buttonClick = (methodName , func = null) => {
        anime[methodName](  ); readyWait( func );
    };
    const play = (speed) => {
        anime.updatePlaybackRate(speed);
        readyWait( isRunning() ? null : ()=>buttonClick("play"));
    };
    const waitMessage = (element,countTime) =>{
        let statTime = null;
        let currentSec = countTime;
        const display = timestamp=>{
            if( statTime === null ) statTime = timestamp;
            if( currentSec < 0 ) { element.textContent = ""; return;}
            const nowSec = countTime - Math.floor( (timestamp - statTime) / 1000 );
            if( nowSec >=0 && currentSec !== nowSec )
                    element.textContent = nowSec.toString();
            currentSec = nowSec;
            requestAnimationFrame( display );
        };
        requestAnimationFrame( display );
    };

    const waitSpan = document.getElementById("wait");
    const animeFunc = {
        stop : ()=>buttonClick( "cancel"  ),
        pause :()=>buttonClick( "pause"  ),
        play1 :()=>play(1), play2 :()=>play(2), play10 :()=>play(10),
        play5s : ()=> {
            anime.startTime =  anime.timeline.currentTime +5000;
            waitMessage( waitSpan , 5 );
        }
    };

    const buttons = Object.entries( animeFunc ).map(
        data => {
            const button = document.getElementById( data[0] );
            button.addEventListener( "click" , data[1] );
            return button;
        }
    );

    readyWait();
});

 

メソッド一覧

 

Animationオブジェクトのメソッド
メソッド名意味
cancel()再生を中止しリセットする
pause()再生を一時停止する
play()再生開始または再開する
reverse()逆再生をおこなう
updatePlaybackRate()再生速度を変更する
finish()再生を終了(最後まで再生した状態)する

 

これらのメソッドを実行しても、即座に反映されるわけではありません。
アニメーションの処理は時間がかかるため、非同期で実行されます。

 

 

プロパティ一覧

 

Animationオブジェクトのプロパティ
プロパティ名変更可否
currentTime現在の再生時間
effectKeyframeEffectオブジェクト
finished終了時に解決するPromiseオブジェクト×(読み取り専用)
idアニメーションを識別するためのID
pending非同期処理の終了待ちかどうかのフラグ×(読み取り専用)
playState再生状況を表す文字列

"idle": 再生していない状態
"running" : delay, endDelayを含んだ再生中の状態
"paused": 一時停止中の状態
"finished" : 最後まで再生した状態

×(読み取り専用)
playbackRate再生速度
ready再生準備完了時に解決するPromiseオブジェクト×(読み取り専用)
startTime再生開始した時間。

anime.timeline.currentTimeにミリ秒を
加算した値をセットすると、
ミリ秒経過後に開始することができる。
このとき、開始待ちでもplayStateは"running"になる。

oncancelcancel イベントハンドラー
onfinishfinish イベントハンドラー

 

けーちゃんおススメJavaScript入門書

  • スラスラ読める JavaScript ふりがなプログラミング
  • プログラム未経験者がJavaScript始めるならコレ!
    コードを掲載して自分で理解しろという投げっぱなしな入門書とは異なり、コードに一つ一つどんなことをやっているかをふりがなという形式で解説しています。
    それでいてJavaScriptの基礎と応用を学べる良書です。
  • これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん
  • JavaScriptの機能を実践で活かすにはHTMLやCSSの知識が不可欠です。
    しかしそれらの知識があることが前提として書かれている書籍が多い中、この本は総合的な知識を身に着けることができます。
    HTMLやCSSの知識も不安な方には、ぴったりの一冊です
  •  

    入門書の役割は、自分のやりたいことをネットで調べることができるようになるための、基礎的な知識の獲得です。
    まずはこれらの本でしっかりと基礎知識を身につけましょう。
    そしてもっと高度なことや専門的なことはネットで調べ、情報が足りないと感じたら書籍を購入してください。


    記事の内容について

     

    こんにちはけーちゃんです。
    説明するのって難しいですね。


    「なんか言ってることおかしくない?」
    たぶん、こんなご意見あると思います。

    裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

    そんなときは、ご意見もらえたら嬉しいです。

    ご意見はこちら。
    https://note.affi-sapo-sv.com/info.php

    【お願い】

    お願い

    ■このページのURL


    ■このページのタイトル


    ■リンクタグ


    ※リンクして頂いた方でご希望者には貴サイトの紹介記事を作成してリンクを設置します。
    サイト上部の問い合わせよりご連絡ください。
    ただしサイトのジャンルによっては、お断りさせていただくことがあります。