[JS] アニメーションを可変

タグ :

これまでの基礎知識を結集して簡易アプリを作成するシリーズです。
今回はアニメーションをページ内で可変するアプリについてです。

アニメーション動作は前記事「ぽよんっ的動作」と同じです。今回はそのアニメーションを自由に設定できる機能を追加しました。
分かり難いですが、右の表がアニメーションの可変箇所です。上から順に動作していきます。表にある「ー」と「+」部分をクリックすると対応する横の数値が変更されます。変更後に円形をいじると、表の数値通りに動作します。まあ、とにかく色々といじって遊んでみてください。

アプリ概要

以下のような仕様とします。

設定項目
 - アニメーション後の要素サイズ
 - アニメーションに要する時間
 - 簡単な操作で変更できる
動作の動的可変
 - データを元にアニメーションを実行させる
 - ページ上の数値をデータとして使用する

必要となる処理は以下になります。

  • クリックイベント
  • 数値計算
  • 指定要素のテキスト取得
  • データ配列への格納処

作成したサンプル

処理の流れとコードは以下になります。

[ 動作フロー ]
js_poyon2_flow
[ コード ]
$(function() {
	var gSize = new Array;
	var gTime = new Array;
	var bSize = parseInt($('.poyon').css('width'));
	var bPos = parseInt($('.poyon').css('top'));
	var timer;
	dataSet();
	$('.poyon').mousedown(function() {
		var pos = bPos + ((bSize - gSize[0]) / 2);
		sizeChange($(this), pos, gSize[0], gTime[0], 0);
	});
	$('.poyon').mouseup(function() {
		myAnimate($(this));
	});
	$('.poyon').mouseout(function() {
		myAnimate($(this));
	});
	$('.minus').click(function() {
		var tag = $(this).attr('class').split(" ");
		var val = parseInt($("li."+tag[0]).text());
		if (tag[0].slice(0, 1) == "s") {
			if (val > 10 && val <= 200) { val -= 10; }
		} else {
			if (val > 0 && val <= 500) { val -= 50; }
		}
		$("li."+tag[0]).text(val);
		dataSet();
	});
	$('.plus').click(function() {
		var tag = $(this).attr('class').split(" ");
		var val = parseInt($("li."+tag[0]).text());
		if (tag[0].slice(0, 1) == "s") {
			if (val >= 10 && val < 200) { val += 10; }
		} else {
			if (val >= 0 && val < 500) { val += 50; }
		}
		$("li."+tag[0]).text(val);
		dataSet();
	});
	function dataSet() {
		var i = 0;
		$('.size ul li').each(function() {
			gSize[i] = parseInt($(this).text());
			i++;
		});
		i = 0;
		$('.time ul li').each(function() {
			gTime[i] = parseInt($(this).text());
			i++;
		});
	}
	function myAnimate(obj) {
		var pos;
		var wait = 0;
		for (var i = 1; i < gSize.length; i++) {
			pos = bPos + ((bSize - gSize[i]) / 2);
			sizeChange(obj, pos, gSize[i], gTime[i], wait);
			wait += gTime[i];
		}
	}
	function sizeChange(obj, pos, size, time, wait) {
		timer = setTimeout(function(){
			obj.stop().animate({
				'top' : pos,
				'left' : pos,
				'width' : size,
				'height' : size
			}, time);
		}, wait);
	}
});
<h4>アニメーションを可変</h4>
<div class="poyon"></div>
<div class="size">
	<p class="table-title">サイズ(px)</p>
	<ul>
		<p>クリック時</p>
		<span class="s0 minus">-</span>
		<span class="s0 plus">+</span>
		<li class="s0">80</li>
		<p>アニメーション</p>
		<span class="s1 minus">-</span>
		<span class="s1 plus">+</span>
		<li class="s1">120</li>
		<span class="s2 minus">-</span>
		<span class="s2 plus">+</span>
		<li class="s2">90</li>
		<span class="s3 minus">-</span>
		<span class="s3 plus">+</span>
		<li class="s3">110</li>
		<span class="s4 minus">-</span>
		<span class="s4 plus">+</span>
		<li class="s4">100</li>
	</ul>
</div>
<div class="time">
	<p class="table-title">時間(ms)</p>
	<ul>
		<p>クリック時</p>
		<span class="t0 minus">-</span>
		<span class="t0 plus">+</span>
		<li class="t0">100</li>
		<p>アニメーション</p>
		<span class="t1 minus">-</span>
		<span class="t1 plus">+</span>
		<li class="t1">100</li>
		<span class="t2 minus">-</span>
		<span class="t2 plus">+</span>
		<li class="t2">100</li>
		<span class="t3 minus">-</span>
		<span class="t3 plus">+</span>
		<li class="t3">100</li>
		<span class="t4 minus">-</span>
		<span class="t4 plus">+</span>
		<li class="t4">100</li>
	</ul>
</div>
.poyon {
	position: absolute; top: 50px; left: 50px;
	width: 100px; height: 100px;
	-webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    background-color: #999;
	background: blue;
}
.size {
	position: absolute; top: 50px; left: 230px;
	background: #aaa; text-align: center;
}
.time {
	position: absolute; top: 50px; left: 380px;
	background: #aaa; text-align: center;
}
.table-title {
	margin: 0 0 0 0;
	padding-top: 5px;
	background: #777;
}
.size ul, .time ul {
	list-style-type: none;
	margin: 0px 10px 0px -20px;
}
.size ul li, .time ul li {
	width: 100px; height: 20px;
	margin-bottom: 10px;
	background: #eee;
}
.minus {
	position: absolute; left: 20px;
	width: 20px; height: 20px;
	background: blue; cursor: pointer;
}
.plus {
	position: absolute; left: 100px;
	width: 20px; height: 20px;
	background: red; cursor: pointer;
}
詳しい説明は後述します。
ページ内の表の「+」と「ー」をクリックすることで対応する数値を動的に変更させています。同時にアニメーション用データを更新しているので、アニメーション動作も変更されます。
前記事の「ぽよんっ的動作」の処理も結構変更箇所があります。設定項目を極力少なくしたかったのでアニメーション用で使うデータを計算で求めるようにしました。

コード解説

jQuery のコードの説明をします。

[ jQuery の説明 ]
[ 2行目〜7行目 アニメーション用データを取得 ]
var gSize = new Array;
var gTime = new Array;
var bSize = parseInt($('.poyon').css('width'));
var bPos = parseInt($('.poyon').css('top'));
var timer;

アニメーション用のデータをサイズデータ格納用配列変数「gSize」とアニメーション時間格納用配列変数「gTime」を宣言します。この2つの変数と、この変数から算出した値により連続アニメーションを動作させます。
また、初期状態のサイズを変数「bSize」に格納し、初期位置を変数「bPos」に格納します。この2つの変数は、アニメーション動作後の要素位置を算出するのに使用します。計算に関しては後述します。
タイマーセットオブジェクトを格納する変数「timer」を宣言します。今回はタイマクリアを行っていませんので無くても大丈夫だと思います。念のために残してあります。。。

dataSet();

上記で宣言した配列変数にデータを格納する処理を行うユーザー定義関数を呼び出します。関数の中身に関しては後述します。

[ 8行目〜11行目 マウスダウン時の処理 ]
$('.poyon').mousedown(function() {
	var pos = bPos + ((bSize - gSize[0]) / 2);
	sizeChange($(this), pos, gSize[0], gTime[0], 0);
});

マウスダウン操作による処理ですが、前回の処理から変更した箇所が2つあります。
1つ目として、要素位置を用意したデータを使うのではなくて、計算によって求めた値を使用するようにしました。計算式は以下になります。


要素の初期位置 + ( ( 要素の初期サイズ – クリック時のサイズ設定値 ) / 2 )

2つ目として、直接データを引数として渡すのでは無く、アニメーション用データ配列の 0番目の要素をマウスダウン時のデータとしました。
上記2つの変更を踏まえて、関数「sizeChange()」へソースコードのようなデータを渡す事でクリック時の動作を実行させています。

[ 12行目〜17行目 マウスアップ時とマウスアウト時の処理 ]
$('.poyon').mouseup(function() {
	myAnimate($(this));
});
$('.poyon').mouseout(function() {
	myAnimate($(this));
});

マウスアップ操作とマウスアウト操作による処理も変更があります。ユーザー定義関数「myAnimate()」を呼び出していますが、この関数については後述します。

[ 18行目〜39行目 「+」と「ー」部分のクリック時の処理 ]
$('.minus').click(function() {

「ー」クリック操作による処理です。「+」クリック操作もほとんど同じ処理なので省略します。

var tag = $(this).attr('class').split(" ");
var val = parseInt($("li."+tag[0]).text());

数値を取得する処理です。
まずクリックされた要素のクラス名を取得します。「ー」要素のクラス名は「s0 minus」のように2つのクラス名が半角スペースで区切られているので、split(” “)でそれぞれを配列「tag」に格納します。配列0番目要素のクラス名(s0)が表内の数値部分の要素のクラス名となっているので、$(“li.”+tag[0]).text() という記述で数値を取得することができます。取得する際に数値として取得できるように parseInt() を用いています。これにより変数「val」には、変更させたい箇所の数値が格納されます。

if (tag[0].slice(0, 1) == "s") {
	if (val > 10 && val <= 200) { val -= 10; }
} else {
	if (val > 0 && val <= 500) { val -= 50; }
}
$("li."+tag[0]).text(val);

数値の計算(減算)をして数値テキストをその計算値に変更します。
分岐処理では、サイズか時間かを判定しています。サイズであれば、10 単位で減算が行われ、時間であれば、50 単位で減算が行われるようにします。また、数値には最小値と最大値を設け、それ以下またはそれ以上の値にならないようにしています。

dataSet();

アニメーションで使用する配列変数にデータを格納する処理を行うユーザー定義関数を呼び出します。関数の中身に関しては後述します。

[ 40行目〜51行目 配列変数のデータを更新する処理 ]
var i = 0;
$('.size ul li').each(function() {
	gSize[i] = parseInt($(this).text());
	i++;
});

ページ内の表の数値をアニメーションで使用する配列変数「gSize」に格納します。each() によりページ内の li 要素をループで回し、上から順番にデータを変数に格納していきます。格納時に parseInt() により整数化しています。
配列変数「gTime」にも同じような処理で格納します。

[ 52行目〜60行目 連続アニメーションの実行 ]
for (var i = 1; i < gSize.length; i++) {
	pos = bPos + ((bSize - gSize[i]) / 2);
	sizeChange(obj, pos, gSize[i], gTime[i], wait);
	wait += gTime[i];
}

アニメーションを forループにより連続して実行させます。
要素位置のデータは、マウスダウン時の処理と同じ計算で求めています。
サイズとアニメーション時間はページ内の表の数値をデータとして使用します。
タイマー時間は各アニメーション時間の加算値で算出しています。

[ 61行目〜70行目 アニメーション実行関数 ]

前記事から変更はありませんので割愛します。

まとめ

パッと見、表が分かり難いですが、結構自信作です。設定も動作も全て 1ページ内でページ遷移すること無くできる点が魅力ではないでしょうか。表のような数値でなく、スライダーとかもっとデザイン性のあるものであれば、色々なページに利用できるかもしれないですな。

ページにやわらかい動きがあると、見ている人も楽しめると思います。キャラクターなんかをこういったやわらかい動作で動かしてみても面白いです。うちのキャラクター(トップページにいるヤツ)も動かしてみようかな。

Share

  • このエントリーをはてなブックマークに追加

Comment

1 Comment

  1. きむらあつとし

    size=80→120→90→110→100
    duration=50→50→100→100→100
    がいい感じかなー。

    Reply

コメントを残す

*がついている欄は必須項目です。

  • Twitter
  • Facebook
  • Google Plus
  • RSS Feed