Webだとか、ましてやインターネット上で見るものは全て横書きで、左から右へ視線が移ります。
でも、Webデザインをしていると、たまに「あ~これ縦書にしてぇな~」ってときがあるんですよね。(もちろん案件で表現したいものを考えた上で)
さらにそのイメージを伝えたりスクリーン上で形にするために、「あ~これjQueryでふわっとフェードインしてぇな~」って感じに決まってしまうときもあるんですよね。
というわけで、jQueryを使ってHTML要素を順にフェードインさせるコードを紹介します!
そして、あまり解説が見当たらない(?)HTMLで記述した順の逆からフェードインさせるコードも書いてみました!
HTMLサンプル
左から順にフェードイン
右から順にフェードイン
CSSサンプル
ul{ margin: 0; float: left; } ul li{ margin: 0 0 0 10px; list-style-type: none; float: right; } section{ overflow: hidden; padding: 1em; } #rtl{ background-color: #ffd; } #ltr{ background-color: #dff; }
それを左から右に読み流すために、float:rightを指定しています。このfloatの向きがが結構大事です。
超簡単。jQueryで要素を順にフェードインさせる
ではまず簡単な方から。
HTMLで上から書いた順にフェードインさせます。floatさせてるので紛らわしいですが、CSSを解除すると上から順にフェードインしてくるんじゃないかなって思います。
上のHTMLサンプルの中の、id=”rtl”の方です。
jQuery
//右から左(HTMLで最初に登場する要素から最後に登場する要素) $('#rtl').find('img').css({"opacity" : 0}).each(function(i){ console.log("#ltr の要素番号 " + i + " は「" + $(this).attr("alt") + "」で " + (i + 1) + "番目にフェードイン"); $(this).delay(1000 * i).animate({"opacity" : 1}); });
理屈はカナリ簡単です。
まず#rtlは、フェードインさせたい要素の親ですね
それを基準としてフェードインさせたい要素をfind()し、それぞれにjQueryのメソッドを使ってcssを指定します。
普通にCSSで指定してもいいのですが、万が一読み込みが遅れた場合に見えないままなので、今回はこの様にした方がベターかと思います。
で、そのひとつひとつに処理をするためeach()を使います。
これが無いと、最初に条件にヒットした要素( $(‘#rtl’).find(‘img’)のこと )だけ取得して満足して終わってしまうので必ず使います。
その下のconsoleはテストなので関係ありません。
F12キーを叩いてコンソールを見ていただくと理解しやすいかなと思って書きました。
その下の$(this)から。
これは、eachで処理している、まさに「処理中の要素」を指します。
それに対し、delay()で処理を遅らせます
.delay() | jQuery 1.9 日本語リファレンス | js STUDIO
ここがキモなのですが、eachの中の関数funciton()で「i」という値を渡しています。
これが処理の回数分(つまり要素の数だけ)カウントアップされていく数値なので、これをdelay()の値にかけることで、後に処理する要素はdelay()で発生するタイムラグがその分大きくなって、”順番”がうまれる。といった構造です。
jQueryでHTML上で後に登場する要素から順にフェードインさせる
まぁ今回のデモの場合だとCSSのfloatの向きとか変えればいいだけなのですが、諸都合でそうも行かない時があります。
前述の手段だとカウントアップされていくだけなので順番に処理していくのは簡単なのですが、
HTML上で後に登場するものから処理するとなると、要素の数からカウントダウンする必要があります。(もっと簡単な方法ありそう…)
そこで、今回はfor()ループを使いましょう
for文-JavaScript入門
実は、プログラミングの基礎基礎基礎クラスぐらいの演習問題みたいな内容です。以下サンプル。
jQuery
$(function(){ //左から右(HTMLで最後に登場する要素から最初に登場する要素) var target = $('#ltr').find('img'); target.css({"opacity" : 0});//透過 var objLength = target.length; for(var i = (objLength - 1); 0 <= i; i--){ var targetImg = target.eq(i); //順番に処理するため var delayNum = 1000 * (objLength - i); //delayの時間差を計算 targetImg.delay(delayNum).fadeTo('slow' , 1 ); console.log("#ltr の要素番号 " + i + " は「" + targetImg.attr("alt") + "」で " + (objLength - i) + "番目にフェードイン終了"); } })
最初のCSSメソッド指定は同じです。
そのあと、objLengthという変数を作っています。
これは、フェードインさせたい要素の「数」です。lengthで取得しています。
String.length – 文字列の長さを得る – JavaScriptリファレンス
その下に、ウワサのfor()ループがあるわけですが、ここで要素の数が役に立つんですね。
ループ回数の上限を決めています。
要素の数は今回の例だと「3」です。フェードインさせたい画像が3つだからですね。
で、そこから1を引いた数をループカウンター「i」としています。
ループ自体の条件ですが、
- 変数iが0と同じか大きい数値である場合はループし、iの数値はカウントダウンされていく。
と言った感じです。解りづらいですかねすみません
それでは処理の話です。
変数targetImgはループ外で定義していた変数targetを、.eq()をつかって要素を選別しています。
eq(position) – jQuery 日本語リファレンス
これは要素の番号です。デクリメント(forの中の–i)でカウントダウンされる「i」の数を引数に指定することで、HTML上で後に登場する要素から取得することが出来ます。
その下のdelayNumは、1つ目の例と同じように時間差を付けるためにdelay()の数値を計算しています。
計算式なのですが、objLengthを使っています。これはフェードインさせたい要素の数ですね。
ここは一定ですが、ループカウンターである「i」の数が変動するため、HTML上で後に登場する要素(=先に処理される要素)はdelayの数値がより小さい状態になるわけです。
同時に動かしてみましょう。
出だしが遅れていますね。
たぶん最初に処理する要素にもdelayがかかっているのでしょう。これはifでなんとかなりそうですが、もう今日はやめておきます。
いかがですかね?
まぁこれ自体は最初にお話したようにfloat:の方向で、なんとかなる場合が多いので簡単な方だけできればいいですよね。
どうしてもh1で囲んでるやつとpで囲んでるやつを順に…とかだと今回のケースが役に立つかと思います。
さいごに+しつもん
今回の例ですが、フェードインと言いつつもfadeInを使っておらず、opacity : 0からのfadeToです。
.animate()でもっと自由にやりたかったのですが、animate()ってdelay出来ないのでしょうか?
2つ目の例で試していたのですがどうしても同時にパパっと出てきてしまうんですね。ここに結構ハマってしまいfadeToに逃げました。
なのでどなたか「そんなのも解かんねぇの?」という強気な方はsatohmsysまでご連絡下さい。ついでに美味しいラーメン屋さんも教えて下さい。
でわ!