jQueryでよく使われて目立つ存在と言えばスライダー。実際に様々なスライダー用jQueryプラグインがありますが、私の場合は簡単なものなら自作しています。最初は勉強がてら作成していましたが、サイトでスライダーを利用するときは必ず自作するようになりました。理由の1つとして、プラグインは汎用性を求められるのでコードは長くなりがちですが(導入サイトには不必要な機能がある場合も)、自分で作成する場合は最低限に抑えることができるのでコードが少なくて済みます。そしてちょっとしたカスタマイズを行う場合、プラグインだと把握に時間がかかるのに対し、自作スライダーは自分で作っているためどこで何をしているか既に把握できているわけです。もちろん使い回す部分もありますが、基本を自分の中に持っておくことでいろいろな応用も可能になるため、要望に応えるスライダーのプラグインを探す手間もなくすことができます。
ここでは、基本となりそうなスライダーを構築するまでと、そこからの応用を書いていきたいと思います。
目次
スライダーの機能/動きを考える
まずはどういったスライダーを作るのかを考えます。自作するにあたって途中であれが必要だったとか今の構造じゃちょっと難しいとか、あとからごちゃごちゃ修正するのを避けるためにも、どのようなスライダーにするかを練ります。基本的には企画やデザインの時点である程度は決まってそうですが。
何をスライドするのか
まずはスライドの中身です。一枚画像なのか、テキストやリンクを含めたテキストなのか、1枚のスライドに対し複数のコンテツを入れたいのかなどなど。この部分はHTML/CSSをどう書くのかに繋がってきます。
- 一枚画像のスライダー
- 比較的簡単なスライダーになります。また画像はwidth:100%だけ指定しておけば横幅、縦幅の比率でエリアを確保してくれるので、レスポンシブデザインにも簡単に対応できます
- コンテンツの入ったスライダー
- 中身にテキストや画像を入れる場合になります。位置をどのようにスタイリングするかが一番の悩みどころになりそうです。特にレスポンシブデザインの場合、フォントサイズやabsolute指定の位置などcssを指定しなくてはならなさそうです。
どうスライドする(切り替わる)のか
スライダーとは言いつつも、横からスライドするもの、フワッとフェードアウト/インをして切り替わるもの、複雑なアニメーションによりダイナミックに切り替わるものなどたくさんの種類があります。この切り替わり方がスライダーの中で一番の活躍どころです。もちろんコンセプトに沿った適切なアニメーションが求められますが。
- フェードイン/フェードアウト
- フェードインとフェードアウトを一番簡単な気がします。
フェードアウト/インでスライドするデモ - 横にスライド
- ザ・スライドという感じのスライド。よく見かけますが意外と奥が深く、同じように見えるものでも裏では全く違うことをしていたりします。スライドを全て横に並べて全体を横に動かす方法、次のスライドをスライドする直前に横に持ってくる方法、前回のスライドは動かず上に重なっていく方法などなど。
横にスライドするデモ - 複雑なアニメーションによるスライド
- jQueryのプラグインではよく見かける複雑なアニメーションで切り替わるスライド。画像が分割されて切り替わったり、ダイナミックに動いたり、新しい技術がりようされていたりと、何これどうなってるの?と思わず興奮してしまいます。作るのにも一苦労、オリジナリティが求められそうです。自作すると言っておきながら複雑なアニメーションを求められると正直プラグインの利用を考えてしまいます。しかし、jQuery自作スライダーのベースをストックしておけば、少しは楽になりそうです。やる気が起きたらデモとして作ってみたいと思います。
スライダーのナビゲーションをどうするか
次/前のスライドへ行くリンクや、今が何番目のスライドなのかなど、ユーザーに優しいスライダーの機能、ナビゲーション。上のデモではナビゲーションはありません。ナビゲーションがないとユーザーはテレビCMを見るかのようにじっと見つめるだけです。ウェブサイトで情報を得るのは基本的に能動的だと思いますが、その分自分のペースで情報を得たい人が多いのではないでしょうか。見ている人によっては早く次のスライドが見たかったり、いつ終わるのか気になる人もいると思います。そんな人へナビゲーションをUIとして設置してあげるのもいいと思います。
ナビゲーションのついたスライダー
- 現在のスライドを示すナビゲーション
- 現在が何番目のスライドなのかユーザーに認識もらいます。繰り返されるGIFアニメーションのごとく、あれこれさっきも見たような…もしかして繰り返してる?なんてことを防ぎます。よく「●○○○」のような形で現在のスライダーはどこか簡易的に分かるものを見たことある人は多いかと思います。画像スライダーの場合はサムネイル画像を並べてナビゲーションとして利用する場合も多いですね。
また、単純に現在のスライドを示すだけではなく、一気にスライドできるよう設定し置いても便利です。 - 次へ/前へ進むスライダー
- 設定した待ち時間より早く次が見たい場合や、逆に次々スライドが進んでしまったので戻りたいときに便利です。ちょうどいい切り替わり速度があればいいのですが、実際のところ人によるところが大きいかと思います。しかし設定する時は、コンテンツの量(画像だとしたらその画像の情報量)に合わせてちょうどいい速度を設定すっればいいと思います。
ちなみに経験からですが、スライダー(メインビジュアル)に対しブランドを重視するクライアントさんだとゆっくり目、宣伝としてたくさん見せたいクライアントさんだと早めに動かす要望が多い気がします。
HTML/CSS/jQueryで組んでみる
スライダーを実際に自作する作業に入ります。まずは簡単なフェードイン/アウトのスライドを組む想定で行います。
フェードイン/フェードアウトするということは、前の画像と次の画像が重なっている必要があります。
HTMLの記述
まずはHTMLになりますが、今回は中身に文章が入る想定です。
注意点としては、スライド1枚1枚に連番が振ってあることです。この処理をjQuery側でも行うことはできますが、それはオプションとして基本を先に構築するのも手です。classの「sld_fade」は、共通のスタイリングをするときや、jQueryでまとめて処理したいときに便利です。
1 2 3 4 5 6 |
<div id="slider"> <div id="sld1" class="sld_fade"><p>スライド1</p></div> <div id="sld2" class="sld_fade"><p>スライド2</p></div> <div id="sld3" class="sld_fade"><p>スライド3</p></div> <div id="sld4" class="sld_fade"><p>スライド4</p></div> </div> |
CSSの記述
次にCSSでスタイリングしていきます。この時点で既にどのような動きをするかを考慮した記述をしなくてはなりません。
スライドとスライドが重なる様に、親要素となる「#slider」には「position:relative」、子要素には「absolute」を指定します。
また、最初はスライドを消しておくため、「display:none」を指定しています。
ここでの注意点は子要素がabsoluteになっているため、親要素の高さが「0」になってしまうことです。「height」で指定するか、下のように「padding」で高さを確保します。このpaddingにパーセント指定をして高さを確保するやり方は、比率を確保しつつ幅に合わせて縮んでいくので、レスポンシブになります。(横 : 縦 = 100 : X から、X = 縦 × 100 / 横 = 61.77%といった感じです。)
1 2 3 4 5 6 7 8 9 10 11 12 |
#slider{ max-width: 960px; margin: 0 auto; padding: 61.77% 0 0; position: relative;} .sld_fade{ width: 100%; height: 100%; position: absolute; left: 0; top: 0; display: none;} |
jQueryの記述
少し長いですが。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$(function(){ var sld_wrap = '#slider', sld = '.sld_fade', sld_pre = 'sld', sld_time = 1000, sld_wait = 3000; $.fn.slide_fade = function(){ return this.each(function(i, elem) { var sldnum = parseInt($(this).data('sldnum')); $(sld).not('#' + sld_pre + sldnum).fadeOut(sld_time); $('#' + sld_pre + sldnum).fadeIn(sld_time); var sld_timer = setTimeout(function(){ sldnum++; if(sldnum > $(sld).length){ sldnum = 1; } $(sld_wrap).data('sldnum', sldnum); $(sld_wrap).slide_fade(); }, sld_wait); }); }; $(window).load(function() { $(sld_wrap).data('sldnum', 1).slide_fade(); }); }); |
ページが読み込まれてから実行する順に説明をしてみます。
最初「var …」により色々と変数に入れています。スピードやID名など、後で変更しやすい様に上の方にまとめておきました。
「$.fn.slide_fade = function(){…」ではごにょごにょしたものが書いてありますが、定義しているだけで実行はしていません。
そして「$(window).load(function() {…」、これは読み込まれた中のものを実行するというものになります。
ページが読み込まれてから「$(sld_wrap).data(‘sldnum’, 1).slide_fade();」を実行していることになります。
- $(sld_wrap).data(‘sldnum’, 1).slide_fade();
-
「sld_wrap」の「sldnum」を「1」に「data」して、「slide_fade」しています。
- 「sld_wrap」は上の方で定義した「#slider」。
- 「data(A, B)」は、ターゲットに対し属性「data-A」を「B」にします。(<div data-A=”b”>)
- 「slide_fadeh()」は少し上で定義している処理ですね。
ここではじめて「slide_fade」のごにょごにょが実行されるわけですが、ポイントはHTMLで記述した連番に対し、「sldnum」が一致したものを表示(fadeIn)し、それ以外を表示しない(fadeOut)処理を行っているところです。
そして、その値を1個増やし、「setTimeout」で自分自身を呼び出すことで無限に続く様にしています。繰り返しの処理があるということはどこかで「1」に戻らないといけないため、全体の数を「length」で数え、それを越えていたら「1」に戻します。
ナビゲーション機能も入れた基本となるスライダー
テンプレートとして持っておけば大分楽になるのかなとおもいます。
上にある「ナビゲーションのついたスライダー」のデモとほとんど同じですが。
HTMLの記述
スライダーの基本はほとんど変わりませんが、ナビ用にHTMLが追加されています。
1 2 3 4 5 6 7 8 9 10 11 |
<div id="slider"> <div id="sld_area"> <div id="sld1" class="sld"><p>スライド1</p></div> <div id="sld2" class="sld"><p>スライド2</p></div> <div id="sld3" class="sld"><p>スライド3</p></div> <div id="sld4" class="sld"><p>スライド4</p></div> </div> <div id="sld_nav"></div> <a id="sld_prev" class="sld_dir_btn">< </a> <a id="sld_next" class="sld_dir_btn">></a> </div> |
CSSの記述
装飾的な部分が多くなってしまいましたが、いろいろ変更してみるといいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#slider{ max-width: 960px; margin: 0 auto; padding: 61.77% 0 0; position: relative;} #sld_area{ width: 100%; height: 100%; position: absolute; left: 0; top: 0; overflow: hidden;} .sld{ width: 100%; height: 100%; position: absolute; left: 100%; top: 0;} #sld_nav{ width: 100%; height: 20px; position: absolute; left: 0; bottom: 20px; text-align: center;} .sld_navi_circle { display: inline-block; width: 16px; height: 16px; margin: 0 4px; border-radius: 8px; background: rgba(255,255,255,0.4); border:2px solid #FFF; box-shadow: 0 2px 0 rgba(0,0,0,0.4);} .sld_navi_circle.current{ background: rgba(255,255,255,1);} .sld_dir_btn{ font-size: 20px; position: absolute; top: 50%; display: block; width: 40px; height: 40px; border-radius: 20px; line-height: 40px; text-align: center; font-weight: bold; margin: -20px 0 0 0; background: rgba(255,255,255,0.4); color: #000; box-shadow: 0 2px 0 rgba(0,0,0,0.1);} .sld_dir_btn:hover{ background: rgba(255,255,255,1);} #sld_prev{ left: 20px;} #sld_next{ right: 20px;} |
jQueryの記述
ちょっと基本というには長すぎますかね。
フェードイン/アウトではナビゲーションがないため、前に戻る処理は必要ありませんでしたが、前に戻る処理が追加されています。
また。「●○○○」をクリックしてその場所へ飛べるように関数も変更し、動くだけの関数、横に行く関数、前に行く関数の3つを作成しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
$(function(){ var sld_wrap = $('#slider'), sld_navi = '#sld_nav', sld = '.sld', sld_max = $(sld).length, sld_pre = 'sld', sld_time = 1000, sld_wait = 2000, sld_timer, goaway_left, from_left, sld_direction; $.fn.slide_move = function(options){ var settings = $.extend( { 'direction': 'next' }, options); return this.each(function(i, elem) { clearTimeout(sld_timer); var sldnum = parseInt(sld_wrap.data('sldnum')); if(settings.direction === 'prev'){ goaway_left = '100%'; from_left = '-100%'; } else { goaway_left = '-100%'; from_left = '100%'; } $(sld + '.current').stop().animate({'left':goaway_left},sld_time); $(sld).not('#' + sld_pre + sldnum).removeClass('current'); $('#' + sld_pre + sldnum).css({'left':from_left}).addClass('current').stop().animate({'left':0}, sld_time, function(){ sld_timer = setTimeout(function(){ sld_wrap.slide_next(); }, sld_wait); }); $('.sld_navi_circle').not('#sld_navi' + sldnum).removeClass('current'); $('#sld_navi' + sldnum).addClass('current'); }); }; $.fn.slide_next = function(){ return this.each(function(i, elem) { var sldnum = parseInt(sld_wrap.data('sldnum')); sldnum++; if(sldnum > sld_max){ sldnum = 1; } sld_wrap.data('sldnum', sldnum).slide_move(); }); }; $.fn.slide_prev = function(){ return this.each(function(i, elem) { var sldnum = parseInt(sld_wrap.data('sldnum')); sldnum--; if(sldnum < 1){ sldnum = sld_max; } sld_wrap.data('sldnum', sldnum).slide_move({'direction': 'prev'}); }); }; sld_wrap.on('click', '.sld_navi_circle', function(){ var sldnum = parseInt(sld_wrap.data('sldnum')); var sldnavi_num = parseInt($(this).data('sldnum')); if(sldnum > sldnavi_num){ sld_direction = 'prev'; } else { sld_direction = 'next'; } sld_wrap.data('sldnum', sldnavi_num).slide_move({'direction': sld_direction}); }); $('#sld_next').click(function(){ sld_wrap.slide_next(); }); $('#sld_prev').click(function(){ sld_wrap.slide_prev(); }); $(window).load(function() { var sld_count = 1; var sld_navi_class; $(sld).each(function(){ if(sld_count === 1){ sld_navi_class = 'sld_navi_circle current'; } else { sld_navi_class = 'sld_navi_circle' } $(sld_navi).append('<a id="sld_navi' + sld_count + '" class="' + sld_navi_class +'" data-sldnum="' + sld_count + '"> </a>'); sld_count++; }); var sld_timer = setTimeout(function(){ sld_wrap.data('sldnum', 1).slide_move(); }, 0); }); }); |
くそ長すぎるんじゃぼけ
言葉も意味わからんわ