javascriptのイージングアニーメーションをプラグインなしで実装する

 どうも、最近Vue.jsをゴリゴリやっているHashiです。

 さて、javascriptでアニメーション処理したい場合にイージングを実装したいケースって多いと思うのですが、今回はプラグインなしで自前でイージング処理をしたい場合の計算式の紹介をしたいと思います。

今回紹介するイージング種類

 イージングの種類は細かい動きも含めるととても多くなるのですが、今回は基本的なイージング処理である下記の3種類を紹介したいと思います。

イージング種類

  • EaseOut
  • EaseIn
  • EaseInOut

環境構築

 まずは、今回のデモとなる簡単な環境を構築したいと思います。なお、今回はChromeをターゲットブラウザとします。

HTML

 今回は3種類のイージングに加えイージングなしの動きも参考として加えたいので、下記のようにそれぞれのターゲット要素を用意した簡単なhtmlファイルにしました。







イージングDEMO



    

Easing Animation

Linear

EaseOut

EaseIn

EaseInOut

 こんな感じでアニメーション表示エリアを作って、その中に各ターゲット要素を配置します。

CSS

 次に上記のコードで読み込んでいる「styles.css」でターゲットを少し装飾します。


@charset "UTF-8";
/* CSS Document */

html,body{
	background-color:#fff;
	margin: 0;
	padding: 0;
}

#animation_area{
	width: 500px;
	height: auto;
	position: relative;
	margin: 0 auto;
	margin-top: 150px;
}

h1{
	padding: 0;
	margin: 0 0 30px 0;
	height: 40px;
	line-height: 40px;
	text-align: center;
}

#animation_area .contents{
	position: relative;
	width: 100%;
}

#animation_area .contents p{
	font-weight: bold;
}

.target_wrapper{
	width: 100%;
	height: 20px;
	position: relative;
}

.target{
	position: absolute;
	background: #000;
	width: 20px;
	height: 20px;
}

 アニメーションエリアを中央表示にして、ターゲット要素を背景黒の20pxの正方形でそれぞれ装飾しています(下の画像参照)。

イージング実装

 さて、上記のように簡単にデモ環境を構築したところで、実際にjavascripでアニメーションとイージングの処理を実装していきます。

 まず先にコードを載せた上でそれぞれ重要となる数式について説明したいと思います。


(function(){

	var target = document.getElementById( 'target' ); //ターゲット要素 Linear
	var target_easeout = document.getElementById( 'target_easeout' ); //ターゲット要素 EaseOut
	var target_easein = document.getElementById( 'target_easein' ); //ターゲット要素 EaseIn
	var target_easeinout = document.getElementById( 'target_easeinout' ); //ターゲット要素 EaseInOut
	var speed = 0; //アニメーション速度初期値 Linear
	var speed_easeout = 0; //アニメーション速度初期値 EaseOut
	var speed_easein = 1; //アニメーション速度 EaseIn
	var speed_easeinout = 1; //アニメーション速度 EaseIn
	var flags = [false,false,false,false]
	var animation;

	animation = requestAnimationFrame( animate );

	function animate() {

		//Linear
		speed += 10; //フレーム更新毎に加算
		target.style.left = speed + 'px'; //ターゲット要素を移動

		if(speed >= 500){
			target.style.left = 500 + 'px';
			flags[0] = true;
		}

		//EaseOut
		speed_easeout += (500 - speed_easeout) * 0.1; //フレーム更新毎に加算
		target_easeout.style.left = speed_easeout + 'px'; //ターゲット要素を移動

		if(speed_easeout > 499){
			target_easeout.style.left = 500 + 'px';
			flags[1] = true;
		}

		//EaseIn
		speed_easein += speed_easein * 0.1; //フレーム更新毎に加算
		target_easein.style.left = speed_easein + 'px'; //ターゲット要素を移動

		if(speed_easein >= 500){
			target_easein.style.left = 500 + 'px';
			flags[2] = true;
		}

		//EaseInOut
		speed_easeinout += (speed_easeinout < 250) ? speed_easeinout * 0.1 : (500 - speed_easeinout) * 0.1; //フレーム更新毎に加算
		target_easeinout.style.left = speed_easeinout + 'px'; //ターゲット要素を移動

		if(speed_easeinout > 499){
			target_easeinout.style.left = 500 + 'px';
			flags[3] = true;
		}

		if(flags.indexOf(false) != -1){
			animation = requestAnimationFrame( animate );
		}

	}

}());


 上記のコードが今回のデモの完成形になります。

 デモ

 全体の流れを簡単に説明すると、それぞれターゲットとなる要素を取得した上で、requestAnimationFrameを使ってターゲットが横に移動するアニメーション処理をしています。requestAnimationFrameの中で各イージングのアニメーションの処理をしており、最終的に全ての要素が目標の位置まで移動したところでrequestAnimationFrameが止まるように設定しています。

 それでは、各イージング処理の重要な部分を説明していきたいと思います。

Linear

 まずは、一応念のためにイージングがかかっていないアニメーションからみていきます。


//Linear
speed += 10; //フレーム更新毎に加算
target.style.left = speed + 'px'; //ターゲット要素を移動

if(speed >= 500){
	target.style.left = 500 + 'px';
	flags[0] = true;
}

 上記がイージングがかかっていない通常の移動アニメーションになります。

 speedという変数にフレームごとに10ずつ加算して、その分ターゲット要素が右に移動していきます。そして、目標値である500を超えた時点でアニメーションがストップするようになっています。これは簡単ですね。

EaseOut(イーズアウト)

 では、イージング処理です。まずは、一番使うケースが多い「EaseOut」から見ていきます。

 EaseOutの動きは最初は加速して、到達点に近づくに連れて徐々に減速していくという動きになります。


//EaseOut
speed_easeout += (500 - speed_easeout) * 0.1; //フレーム更新毎に加算
target_easeout.style.left = speed_easeout + 'px'; //ターゲット要素を移動

if(speed_easeout > 499){
	target_easeout.style.left = 500 + 'px';
	flags[1] = true;
}

 上記がEaseOutアニメーション処理の流れになりますが、大枠の処理はイージングなしのLinearとほぼ同じです。

 このコードの中で一番重要なのが3行目の数式の部分ですね。

 この数式が実際にEaseOutの動きを実現しています。一見少し難しいように思うかもしれませんが、一度法則を覚えてしまうと簡単です。その法則が下記。


始点 += (到達点 - 始点) * スピード調整値;

 先ほどの数式を書き換えると上記のようになります。この法則で覚えておくととても簡単です。それぞれの環境に合わせて到達点と始点を変えるだけで流用できます。

EaseIn(イーズイン)

 続いて、「EaseIn」を見ていきましょう。

 EaseInの動きは最初は遅く、到達点に近づくに連れて徐々に加速していく動きになります。EaseOutと逆の動きですね。


//EaseIn
speed_easein += speed_easein * 0.1; //フレーム更新毎に加算
target_easein.style.left = speed_easein + 'px'; //ターゲット要素を移動

if(speed_easein >= 500){
	target_easein.style.left = 500 + 'px';
	flags[2] = true;
}

 上記がEaseInアニメーション処理の流れになります。こちらも大枠はこれまでのコードと同じになります。

 ここで実際にEaseInの動きを実現しているのが3行目の数式になります。

 これはEaseOutと違ってすごく簡単ですね。最初は遅く、徐々に加速していけばいいだけです。これも下記のように覚えておくと便利です。


始点 += 始点 * スピード調整値;

EaseInOut(イーズインアウト)

 では、最後のイージング「EaseInOut」を見ていきましょう。

 EaseInOutの動きは最初は遅く、その後加速して、到達点に近づくに連れてまた徐々に減速していく動きになります。その名の通りEaseInとEaseOutを合わせた動きになります。


//EaseInOut
speed_easeinout += (speed_easeinout < 250) ? speed_easeinout * 0.1 : (500 - speed_easeinout) * 0.1; //フレーム更新毎に加算
target_easeinout.style.left = speed_easeinout + 'px'; //ターゲット要素を移動

if(speed_easeinout > 499){
	target_easeinout.style.left = 500 + 'px';
	flags[3] = true;
}

 ここで重要なのは3行目ですね。

 EaseOutとEaseInに比べて少し複雑になっていますが、これも法則として覚えてしまえばいたって簡単です。


始点 += (始点 < 到達点の中間地点) ? 始点 * スピード調整値 : (到達点 - 始点) * スピード調整値;

 このコードの中でやっていることは、目標地点の中間地点までEaseInの処理をして半分をすぎたらEasseOutの処理をしています。1つのコードでやっていますが中身はif文になります。

 このようにそれぞれ法則として覚えておけばイージングの処理もプラグインを使わずとも簡単に実現できるので覚えておくと役に立つかもしれませんね。

 デモ

 なお、今回は移動アニメーションで実装しましたが、同じ原理でフェード等のアニメーションにも流用できるのでお試しください。

まとめ

 いかがでしたでしょうか?

 今回はjavascriptでプラグインを使わずにイージング処理を実装する方法を紹介させていただきました。一昔前のFlash全盛期の時代にはActionscriptで紹介したようなイージング処理を実装していましたが、様々なイージングプラグインが誕生するに連れ書くことも少なくなりましたが、最近はcanvasだったりThree.jsでコンテンツを作る機会も増え、イージングの処理もまたスクラッチことも増えてきた印象がありますので、ご参考になれば。

 ということで、今回はここまで!Hashiでした。また!

お仕事のご相談・ご依頼
お気軽にお問い合わせください!

お仕事の依頼はこちら

著者プロフィール

Taka

東京、奄美大島を拠点にサーフィンとスノーボードが好きなフリーランスのWebクリエイターです。普段はプログラム書いたりデザインしたり映像作ったりしています。いろいろな人の話しを聞くのが好きなので、このブログを通して多くの人と繋がりが出来たら嬉しいです。noteとInstagramもやっているのでフォローしてくれたらありがたいです!

人気記事

  1. ライブラリとかCSSなしでアニメーションさせる方法を探していて、すごく参考になりました!
    ありがとうございます

コメントを残す

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