[MooTools Tutorial]横からスライドインしてくるアニメーションメニューの作り方

何か最近巷がjQueryマンセーな感じで、MooToolsフリークとしては肩身が狭い今日この頃
MooToolsがマイナーなのはドキュメントが少ないからだ!と言われてるようなので、
新しいカテゴリなど追加しつつ手取り足取りなチュートリアルを書いて行こうと思います。

このエントリーでは、MooToolsのFx.Morphクラスを使ってリスト要素をFlashのようにぬるぬる動かします。
完成するとリストメニューが上から順に画面中央付近から左側へスライドインしてくるアニメーションになります。

View Demo Page

MooToolsのCoreとMoreについて

今回はCoreに内臓されているクラスを使うのでMoreのクラスは必要ありません。
スクリプトを利用するのにダウンロードが必要なのはダウンロードページのトップにあるMooTools 1.2.4のファイルです。

mootools_download

ダウンロードするとmootools-1.2.4-core.jsみたいに、バージョンの後ろにcoreと入ったファイル名になります。
(.txtの拡張子を削除して拡張子を.jsにすること)
MooToolsを利用する場合はこのCoreファイルがあればOKです。

プラグインによってはMoreのクラスが必要になる場合があります。
大体はプラグインに合わせたCoreとMoreがセットで配布されているのですが、
別途ダウンロードが必要な場合は、ダウンロードページの右側にあるメニューからMore Builderに移動し、
必要なプラグインを選択してダウンロードします。

CoreファイルもCore Builderに移動すれば必要な機能だけチョイスして作成することが出来ます。
使わない機能を削除すればファイルサイズを減らす事が出来るので、覚えておくと便利です。

※注意
ある程度経験のある方を対象にしていますので

  • HTMLやXHTMLが分からない
  • CSSも良く分からない
  • Javascriptの基本的なことが分かってない
    (インスタンスとかメソッドとか言われても意味が分からない…という人は
    インスタンス=複製したもの メソッド=関数 と置き換えればなんとかなると思います)

みたいな方は対象外になります。

Step1:画面を作る

アニメーションが終わった状態の画面を適当に作ります。今回は横スライドなので縦に並べました。
リスト要素には必ずIDを振ってください。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr">
<head profile="http://purl.org/net/ns/metaprof">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MooTools Fx.Morph Scroll Animation DEMO</title>
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/reset/reset-min.css" />
<style type="text/css">
<!--
	html { background-color:#000; color:#666; }
	body { font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;}
	ul { margin:50px; }
	li { margin:0 0 10px 0;}
	a { color:#fff; font-size:200%;text-decoration:none;}
	a:hover { color:#80ffff;}
	#footer {overflow:hidden;_zoom:1;}
	#footer li {float:left;margin-left:-1px;padding:0 5px;border-left:solid 1px;font-size:77%;line-height:1}
-->
</style>
</head>
<body>
	<ul id="global-navi">
		<li><a href="#">HOME</a></li>
		<li><a href="#">NEWS</a></li>
		<li><a href="#">TOPICS</a></li>
		<li><a href="#">ABOUT</a></li>
		<li><a href="#">BLOG</a></li>
		<li><a href="#">CONTACT</a></li>
	</ul>

	<ul id="footer">
		<li>powered by MooTools</li>
		<li>copyright © Tenderfeel all rights reserved.</li>
	</ul>
</body>
</html>

こっそりYUIのcssを使用

Step2:MooToolsのCoreを読み込む

head内にスクリプトタグを1行入れるだけです。

<script type="text/javascript" src="mootools-1.2.4-core.js"></script>

入れる場所はbodyの閉じタグ直前とかでもいいんですが、これから書くソースより前に読み込まれてないとエラーになります。

Step3:addEventでdomreadyする

type=javascriptなscriptタグを新しく追加し、イベントを実行するためのスターターを書きます。

<script type="text/javascript">
//<!&#91;CDATA&#91;
window.addEvent("domready",function(){

});
//&#93;&#93;>
</script>

windowオブジェクトにdomreadyイベントを追加→DOMが読み込まれたら引数の関数を実行 っていうソースなんですが、
MooToolsでページを読み込まれた時に何かするときはほぼ100%の確率でこの書式を使います。

Step3:リスト要素を取得する

上で書いたソースにリスト要素を取得するソースを追加します。
リストにはIDが振ってあると思うので、ドル関数を使います。

ちなみにMooToolsのドル関数はdocument.getElementByIdなので、IDを持つ要素しか取得出来ません。
(jQueryのように要素を作る機能もありません)
CSSセレクタやタグ名で取得する場合はドルが2つになります。( 例:$$(".navi")

var list = $("global-navi");

上記のソースで変数listに入るのはUL要素です。
LI要素はUL要素の子なので、後ろにElementクラスのgetChildrenメソッドを繋ぎます。

window.addEvent("domready",function(){
	var list = $("global-navi").getChildren();
});

これで変数listにスライドさせるLI要素が格納されました!
FirefoxにFireBugを入れていればconsole.log(list);でLI要素を確認できます。

Step4:eachでFx.Morphのインスタンスを作成する

Step3でLI要素が変数listに配列形式で格納されました。

アニメーションを作るために使えるCoreのFxクラスはTweenとMorphがあるんですが、
Tweenは透明度や横幅などのプロパティを1つしか操作できず、
Morphは複数のプロパティを一度に操作出来るという違いがあります。
そういうわけで今回はmargin-leftと透明度を扱うのでMorphを選択しました。

作成したFx.Morphのインスタンスは次のステップで実行します。
一旦配列にしまっておく必要があるので、新しく変数morphを定義します。

window.addEvent("domready",function(){
	var list = $("global-navi").getChildren();
	var morph = [];
});

Fx.MorphのインスタンスはLI要素それぞれに対して作成しなければならないので、配列を順に処理する超便利なeachメソッドを使います。
基本的にeachメソッドは次のような書き方になります。

list.each(function(el,index){
//処理とかいろいろ
});

elには配列の値(この場合はLI要素)、indexは値が持つキー番号です。

FxやFx.Morphについて詳しく書くとそれだけでエントリー1つ消費できてしまうので、
詳細はリファレンス和訳版)を見てください。

Morphに限らず、Fxクラスに共通する書式はこうです↓

var myFx = new Fx.Morph(element[, option]);

//element:IDかHTML要素のオブジェクト
//option:Fxのオプション(durationやtransitionなど)

今回は配列に格納されてるLI要素をeachで処理するため、elementの部分が引数elになります。
Fx.Morphはインスタンス作成と同時にsetメソッドにより初期状態を設定出来るので、
後ろにset()を繋げて、margin-leftを500px、opacity(透明度)を0(非表示)にしておきます。

window.addEvent("domready",function(){
	var list = $("global-navi").getChildren();
	var morph = [];

	list.each(function(el,index){
		morph[index]= new Fx.Morph(el,{duration:1000, transition:Fx.Transitions.Expo.easeOut})
		.set({"margin-left":500,"opacity":0});
	});
});

これで変数morphにはFx.Morphのインスタンスが格納されます。
あとはこいつを動かすだけです。

Step5:periodicalで繰り返し実行

「上のやつから順番にスライドインさせる」というアニメーションはコンマ何秒かの間隔を開けて順番に実行させなければ出来ません。
「○秒おきに実行させる」というのはMooTools使わなくてもsetTimeoutとかで出来るんですが、
これはMooToolsのCooKBookなので敢えてFunctionメソッドのperiodical()を使います!

periodicalについても詳細はリファレンス和訳版)を見ていただくとして、
基本的な書き方はこちら↓

var intervalID = myFunction.periodical(period[, bind[, args]]);

//myFunction:繰り返し実行させる関数
//period:タイマー(ミリ秒単位で指定)
//bind:実行させる関数内で'this'として参照したいオブジェクト
//args:実行させる関数に渡す引数
//戻り値:periodicalによって割り振られたID番号

これだけじゃどんな動き方するのか想像つかないと思うので実際に書いてみることにしましょう。
まず、実行上限と実行している番号を格納する変数counterを作成し、
オブジェクト形式でcount:0とmax:0を設定しておきます。

	var counter = { count:0, max:0 };

eachメソッドの最後の行でキー番号を変数counterのmaxに保存します。
最終的にmaxは一番最後のキー番号と同じになります。

window.addEvent("domready",function(){
	var list = $("global-navi").getChildren();
	var morph = [];
	var counter = { count:0, max:0 };//カウント用
	
	list.each(function(el,index){
		morph[index]= new Fx.Morph(el,{duration:1000, transition:Fx.Transitions.Expo.easeOut})
		.set({"margin-left":500,"opacity":0});
		
		counter.max = index;//キー番号保存
	});
});

さて、繰り返し処理ですが、関数は匿名関数でいいので入れ物は次のようになります。
これをeachの後ろに追加します。

(function(){ }).periodical(300);

periodicalの第二引数にcounterを追加。
これで、匿名関数内のthisの参照先がcounterになりました。

(function(){ }).periodical(300, counter);

匿名関数の中でFx.Morphをstart()させます。
インスタンスは変数morphに配列形式でしまってあるので、実行するインスタンスをキー番号で指定する必要があります。
ここで変数countercountを使用します。

(function(){
	morph[this.count].start({"margin-left":0,"opacity":1});
}).periodical(300, counter);

カウントアップさせないと動かないので、匿名関数の最後でcountを+1します。

(function(){
	morph[this.count].start({"margin-left":0,"opacity":1});
	this.count++;
}).periodical(300, counter);

しかしこれでは無限ループしてしまいます。エラーで止まるけどよい子は無限ループの実行をしないでね!

countmaxと同じ値になったら実行を止めなければいけませんが
関数内でreturnしても無駄なので、periodicalなどのタイマー関数をストップさせる$clear()を使います。
$clear()でperiodicalの実行を止めるには引数にperiodicalの戻り値が必要なので
変数repeatに入れてから匿名関数の中にif文を追加して、countmaxが同じ値だった場合に、$clear()を実行させるようにします。

var repeat = (function(){
	if(this.count == this.max) $clear(repeat);
	morph[this.count].start({"margin-left":0,"opacity":1});
	this.count++;
}).periodical(300, counter);

これで画面中央付近から左側へぬるっと滑り込んでくるアニメーションが出来たはずです。
無事完成したら適当に値を変更して遊んでみてください。

ソース全文はデモページで確認できます。

Coreドキュメントの和訳は高橋文樹さんがやってます!GJ!

Leave a Comment.