【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要素からアクセスできるメソッドです。
次のような構文で、二つの引数を受け付けます。
引数の値の一部は、CSSのプロパティ名を指定します。
"-"が含まれるプロパティ名は、"-"を取り除き、続く一文字を大文字で表記するキャメルケースで記述します。
例:
background-color → backgroundColor
引数1:キーフレーム
一番目の引数は、変化させたいCSSスタイルを列挙します。
列挙方法は、次の二つの方法があります。
スタイル値を配列で指定
変化させたいスタイルをプロパティ名としたオブジェクトを指定します。
各プロパティの値は、変化させたい値を順番に並べた配列です。
指定例
配列の要素は、一番目の値が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プロパティは次の値を指定できます。
値 | 意味 |
---|---|
"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 イージング確認ツール
スタイルの組を配列で指定
スタイル値を組み合わせたオブジェクトを、順番に並べた配列です。
こちらも方法でも、offsetやeasing指定が可能です。
[
{
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%へ変化 |
easing | アニメーション動作の変化率 | easingプロパティの値参照 |
endDelay | 再生終了後の待機時間 | ミリ秒(規定値は0) |
fill | アニメーション前後の状態 | "none" : delay中を含めてcssのみ適用 |
iterationStart | 再生開始のタイミング。 0.2とした場合、20%から100%の次に | 0以上の小数(規定値は0) |
iterations | 再生回数 | 0以上の小数(規定値は1) Infinityを指定すると、無限ループする |
id | アニメーションを識別するためのID | 文字列で指定 |
composite | CSSなどの元となる状態と アニメーションの現在の状態との処理方法 | "replace" : アニメーションの現在の状態で置き換え "add" : 元となる状態にアニメーションの状態を追加 "accumulate" : 元となる状態にアニメーションの状態を累積 規定値:"replace" |
iterationComposite | 繰り返し時の状態の取り扱い方法 | "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();
});
メソッド一覧
メソッド名 | 意味 |
---|---|
cancel() | 再生を中止しリセットする |
pause() | 再生を一時停止する |
play() | 再生開始または再開する |
reverse() | 逆再生をおこなう |
updatePlaybackRate() | 再生速度を変更する |
finish() | 再生を終了(最後まで再生した状態)する |
これらのメソッドを実行しても、即座に反映されるわけではありません。
アニメーションの処理は時間がかかるため、非同期で実行されます。
プロパティ一覧
プロパティ名 | 値 | 変更可否 |
---|---|---|
currentTime | 現在の再生時間 | 〇 |
effect | KeyframeEffectオブジェクト | 〇 |
finished | 終了時に解決するPromiseオブジェクト | ×(読み取り専用) |
id | アニメーションを識別するためのID | 〇 |
pending | 非同期処理の終了待ちかどうかのフラグ | ×(読み取り専用) |
playState | 再生状況を表す文字列 "idle": 再生していない状態 | ×(読み取り専用) |
playbackRate | 再生速度 | 〇 |
ready | 再生準備完了時に解決するPromiseオブジェクト | ×(読み取り専用) |
startTime | 再生開始した時間。 anime.timeline.currentTimeにミリ秒を | 〇 |
oncancel | cancel イベントハンドラー | 〇 |
onfinish | finish イベントハンドラー | 〇 |
更新日:2021/09/09
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。