JavaScriptTweetPocketWebサイトでは必ずと言っていいほどよく見かけるスライダーUIですが、どういった仕組みで動いているか知っていますか?いまや便利で高機能なjQueryプラグインがたくさんあるため、わざわざイチから作る機会は少ないと思います。仕組みを知っておけばプラグインで対応できない場合に作ることができますし、プラグインをカスタマイズして実装することもできるようになります。自分で作ることができるようになると仕様をプラグインに縛られることがなくなるため、わがままな要求にも応えられるようになります。なにより自分で作って動いてるものを見ると楽しいこと間違いなしです。いったものでバグが見つかったときの焦り具合も尋常じゃありませんが。いうことで、スライダーの作り方と仕組みを初心者向けに解説していきたいと思います。(ここでいう初心者とはHTML・CSS・jQueryの基本がわかる程度です)※IE8〜11、Safari(Mac)、Firefox、Chromeで動作確認しています。今回作るスライダーは・・・はい、これです。別ウィンドウで開くよく見る形だと思います。先に仕組みをひとことで言っておくとfloat(*1)で横に並べた要素を左右にずらしているだけです。簡単そうに言ってるからなのか、すごく簡単そうですね!*1...floatである必要はなく、とにかく横に並べばいいです。解説するにあたってテンプレートを作って環境を合わせたいと思います。--></body></html>slider.htmlという名前で保存し、jQueryは公式サイトからダウンロードしてslider.htmlと同じフォルダに入れておいてください。Chromeを使いますが、FirefoxでもSafariでも大丈夫です。HTMLとCSSを作るjQueryによるスライダーということでjQueryの話しがメインになるかと思いきや実は違います。スライダーUI以外にも言えることですが、HTMLとCSSをしっかり組むことが大事です。それをjQueryで動かすだけ。jQueryは添えるだけ。jQueryは添えるだけ。・ということで、添えるだけのjQueryは一旦忘れてHTMLで次のような構造を作りましょう。class="slide">slide5</div></div></div>コードを見ると3種類のクラスがついたdivがあることがわかると思います。このdivは、それぞれ画像やテキストなどのコンテンツを入れるdiv.slideそれを格納して移動するdiv.slideSet表示領域を制御するdiv.sliderといった役割を持ちます。この構造と役割がとても大事です。覚えておいてください。次にこの状態でスライダーのように見せるためのスタイルシートを作ります。jQueryは使いません。スタイルシートではdiv.slideを横に並べ、div.slideSetの幅を広げ、div.sliderでスライダー全体の幅をdiv.slideと同じにしたうえではみ出した部分を非表示にするといったことを行います。ここではサイズ500×200pxの画像を5つ並べるという想定でスタイルシートを作っていきますが、実際にはスライダーに使う画像やコンテンツのサイズに合わせて変更してください。div.slideを横に並べます。floatを使いましょう。あと実際には必要ありませんが、ここではdiv.slideの境界がわかるように線をつけておきます。left;}続いてdiv.slideSetの幅を広げます。横一直線に並べるのでカラム落ちしないようにdiv.slideSetに「div.slideの幅×div.slideの数」の幅を指定します。2500px;}一度ここでプレビューしてみましょう。うまく出来ていればdiv.slideが横に並び、ウィンドウを突き抜けていると思います。div.slideがカラム落ちして2段になっている場合は、div.slideSetの幅が足りてないはずですので、もう一度「div.slideの幅×div.slideの数」で数値を計算してみてください。hiddenではみ出した部分を非表示にしてしまいましょう。hidden;}再びプレビューしてみましょう。slide1だけが表示されていると思います。これでスライダーのHTMLとCSSが出来上がりました。図にして整理すると・・・こういう構造になっています。実はこのままでは問題が1つあります。それはdiv.slideSetの幅を計算してスタイルシートで指定している部分です。実際にはdiv.slideの数は増減しますし、幅も変わるはずです。ここはdiv.slideの数と幅に合わせて自動的に計算された幅が指定されなければいけません。ここからいよいよjQueryの出番です。div.slideSetの幅をjQueryを使って計算して指定する「jQueryを使って計算」と書くのはちょっと誤解を生むかもしれません。実際は「jQueryでdiv.slideの数と幅を取得してJavaScriptで計算してjQueryでスタイルシートを指定する」ということなんですが、使い分けて書くのは煩わしく、読みにくいのでjQueryということで統一します。ちなみにjQueryはJavaScriptライブラリのひとつでjQueryを使っても裏側で動いてるものはJavaScriptです。ここを間違えると恥ずかしいので気をつけましょう(気をつけます)。それではとりあえず、jQueryで幅と数を取得してそれを変数に入れるコードを書いてみます。.slideの数を取得して代入$(selector)で.slideを参照、outerWidth()で幅、lengthで数を取得し、それぞれslideWidthとslideNumという変数に代入しています。このslideWidthとslideNumを掛け算した値がdiv.slideSetの幅になるわけですね。ちなみに、outerWidth()を使っているのはdiv.slideにborderが指定されているためです。width()ではborder分が加算された幅を取得できず計算が合わなくなります。div.slideにborderやpaddingが指定されていない場合にはwidth()でも大丈夫です。slideNumで計算した値をdiv.slideSetに指定しましょう。slideNumの値を代入し、$(selector)で.slideSetを参照しスタイルシートのwidthにslideSetWidthを設定する。Toolsを開いてwidthが指定されているか見てみましょう。ToolsのElemetnsタブでdiv.slideSetにwidthが指定されていれば正しく動作しています。指定されていない場合は、jQueryを読み込めていないかコードにミスタイプがあると思いますので確認してみてください。2500pxは不要になるので削除してください。left;}</style>これでスライダーの形ができました!これを今度は動かしていきましょう。jQueryでアニメーションを実行するアニメーションはスタイルシートを連続で更新してHTML要素を動かすことによって表現します。その動きをjQueryではanimate()を使って簡単に作ることができます。アニメーションさせてみましょう。動かす対象はdiv.slideSetです。この要素の位置が左にdiv.slideの幅分動けばslide1からslide2へスライドして見えるわけですね。いうことでこのようなコードになります。-slideWidth});これでアニメーションが実行されるかと思いきや実はされません。プレビューしてみましょう。Toolsで見てみるとdiv.slideSetのleftが高速で書き換えられているのは確認できます。jQueryはうまく動作しているわけですね。absoluteが指定されていないからです。absoluteを指定すればいいわけですが、それだけだとdiv.slideSetの親がbody要素になっているため、位置がおかしくなります。absoluteが指定された子要素は非表示になりません。以上のことを対策するとdiv.sliderとdiv.slideSetのスタイルシートはこうなります。absolute;}再びプレビューしてみましょう。わかりにくいですが、さっきまでslide1があった位置にslide2がアニメーションして移動してきました。absoluteの方が処理が軽くなります。transformが使える条件であればtransformの方がスムーズにアニメーションして見えます。いまは勝手にslide2へスライドしてしまいますので、これを「次へ」ボタンが押されたときに実行するようにしてみましょう。スライドアニメーションを実行するボタンを作るボタンはなんでもいいのですが、ここではbutton要素を使います。あとで前へ戻るボタンも必要になるのでbutton.slider-nextとしましょう。class="slider-next">次へ</button>このbutton.slider-nextがクリックされたときに先ほどのアニメーションが実行されればいいわけですね。jQueryで特定の要素がクリックされたときのイベントを作るにはclick()を使います。このclick()の第一引数にはクリックされたときに実行するコードを登録できます。さきほどのアニメーションするコードをそのまま入れてもいいのですが、あのコードは「戻る」ボタンがクリックされたときにも使いたいと思いますので、独自関数を作ってそれを実行させましょう。次へボタンが押されたとき$('.slider-next').click(function(){sliding();});プレビューしてみましょう。「次へ」ボタンを押すと・・・動きましたね!さてさて、いよいよスライダーっぽくなってきました。動きだけ見ればもはやスライダーといっても過言ではありません。このスライダーを真のスライダーにするためにいまの問題点を挙げてみましょう。slide2へはいけるがslide3〜5へいけないというか、slide1にも戻れないといったところでしょうか。現在地を示すナビゲーションも欲しいところですが、それはまたの機会に。それではこの問題を解決していきましょう。-slideWidthとなっているため何をしても同じ位置にしか移動しません。-スライドの幅」となります。ここで注意点がひとつあります。0ですので、実際には1番目は0番目として考えなければいけません。この計算式の中で「移動したいスライドの番号」を知る方法がいまはありません。この番号を知るためには、まず現在地を知らなければいけません。そのために現在地を記録しておく変数を用意します。この変数は「次へ」がクリックされたときに+1され、「前へ」がクリックされたときには-1されるものです。これによって次に移動するスライドの番号がわかるという仕組みです。この現在地=移動したいスライドの番号というわけですね。スライドの番号がわかれば、あとは先ほどの計算式に当てはめてleftの値を求めることができます。次へボタンが押されたとき$('.slider-next').click(function(){slideCurrent++;sliding();});はじめの位置はSlide1になるので変数slideCurrentには0を代入しています。.slider-nextがクリックされたときにslideCurrentに1を加算しアニメーションを実行する関数を実行します。-slideWidth」という計算式によってleftの値を求めて指定しています。プレビューしてみましょう。Slide1から5まで動きましたね!そしてクリックし続けると通り過ぎますね・・・。新たなる問題が発生しましたが、とりあえず斜め前あたりの微かに見える程度の位置において「前へ」ボタンを実装を進めましょう。「次へ」ボタンと同じような形で実装できるので簡単です。次へボタンが押されたとき$('.slider-next').click(function(){slideCurrent++;sliding();});再びプレビューしましょう。慣れないうちは細かくプレビューしないと問題を発見できなくなりますからね。これで次のスライドへも前のスライドへも自由自在に動きましたか?動かない場合は「前へ」ボタンのクラス名が正しいか、-1されているか確認してみてください。終わりが見えてきました。先ほど斜め前あたりの微かに見える程度の位置においた問題(クリックし続けるとスライドが彼方へ行ってしまうという問題です)を持ってきて解決しましょう。スライドをループさせるこの問題は現在地がずっと加算(または減算)されているため、div.slideの数を超えて見えなくなってしまうという現象です。現在地に入る値を0〜スライドの数の間で制限してやれば解決することができます。この制限をする方法としては、0以下になったときに0に戻して処理を止める0以下になったときにスライドの数を代入して最後のスライドに移動させてループさせるのどちらかがベターです。スロットルーレットのように一方行にずっとループして進み続けるといったものもできますが、それはまたの機会に。今回は2番の方法を採用します。処理の流れとしては、「もしslideCurrentが0未満だったらslideNumの値を代入する。slideCurrentがslideNumを超えていたら0にする。どちらでもなかったらそのまま処理を実行する」という感じです。それではコードにしてみましょう。条件判定をするタイミングとしてはanimate()が実行される直前になるので、独自関数のsliding()の中に書いていきます。ここでひとつ注意点があります。slideNumにはlengthで取得したスライドの数「5」が入っていますが、slideCurrentは0から始まっているため、番号がひとつずれている状態です。slideNumから1を引いてやらなければいけません。-slideWidth});}プレビューしてみましょう。これで基本的なスライダーは完成しましたが、ボタンを高速でクリックするとクリックを止めてもアニメーションが止まらずに再生され続けませんか?この問題を解決してちょっとだけ完成度を上げてみましょう。jQueryアニメーションをstop()で制御する「ボタンを高速でクリックするとクリックを止めてもアニメーションが止まらない」という現象はアニメーションのキューが溜まっているから起こる問題です。このキューはanimate()が実行される度に発行され、アニメーションが終わった時に削除されます。そのため、アニメーションが終わる前に新たなキューが発行されると1,2,3,4...と溜まっていき、1番のアニメーションが終わったら2番のアニメーションを実行し、それが終わったら3番、更にそれが終わったら4番と連続でアニメーションしてしまうわけです。これを解決するにはanimate()を実行する前にキューを削除したり、再生されているアニメーションを終わらせてやります。そのために必要なものがjQueryのstop()です。これはアニメーションを終わらせるための関数で、引数でキューを削除したり、アニメーションの終わり方を現在の再生フレームで終わりとするか、最後の再生フレームで終わりとするか制御することができます。今回はanimate()が実行される前にアニメーションを終わらせてしまえば、キューが溜まらずクリックを止めた時点でアニメーションも止まるため、引数は特に指定しません。いうことでコードはこちら。メソッドチェーンを使用してanimate()の前に記述します。-slideWidth});プレビューしてみましょう。高速でクリックして止めてもアニメーションが止まりましたね。このようにユーザーのアクションによって動作するアニメーションはキューが溜まってしまうため、stop()で制御してあげましょう。ちなみに、is(‘:animated’)などを使用してアニメーション中はクリックしてもその場で処理を止めて、アニメーションを実行させないという方法もありますが、これはユーザーのアクションに対してレスポンスを返していないため、「反応しない。なんで???」となり困惑しますので、あまりいい方法ではありません。これで終わりと思いきやまだ終わりません。確かに動きはできたのですが、使用している変数がグローバル変数になっているため、他のJavaScriptと競合する可能性があります。これを解決するために即時関数を作って実行します。即時関数にする即時関数というのはその名の通り、作ったら直ぐ実行される関数のことです。これによりローカル変数を作れるため他のJavaScriptとの競合を回避することができます。}())で簡単に作ることができます。略}());</script>プレビューしてちゃんと動くか確認してみましょう。これでスライダーの基本機能が備わったものが完成しました。あとは画像を入れたりデザインしたり自分なりに調整してみてください。僕はこんな感じにしてみました。まとめjQueryを使う前にHTMLとCSSで形を作る。コンテンツを入れるdivを作る。コンテンツの数×幅の大きさを持つdivを作る。hiddenで見える部分を制御するdivを作る。3のコンテンツの数×幅はjQueryを使って計算して指定する。animate()で動かすものはひとつだけ。現在地を知ることでスライドの位置を計算することができる。stop()でアニメーションのキューを制御する。おわりに初心者向けということでできる限り不要な機能・情報を省いたシンプルな内容になりましたが、どういうふうにスライダーが動いていて、それをどう実現しているのか、スライダーの基礎部分は伝えられたかな。今度はこれを元にjQueryプラグイン化したり、機能を追加する記事を書いて見ようと思います。)ノシ追記(2015/12/02)変数名がslidecurrentとなっているところがあったのでslideCurrentに修正しました。slimeさんご指摘ありがとうございます。【スライドをループさせる】のソースコードでslideCurrentのところがslidecurrentとCが小文字になっております。