JavaScriptでなるべく簡単にサムネイル付きスライダーを自作するIT系おじさんのチラシの裏2018年10月~プロフィールAUTHOR:とっちら書きたくなったときに書きたいことを書く雑記ブログ。IT系のネタが多いかも知れません。11:57とっちら1年前の記事に助けられました。14:28とっちらこの記事のお陰で60分録画できるようになりました。16:01とっちらライセンスを明示して貰えると使いやすいのですが。14:37ご回答いただきどうもありがとうございます。21:56とっちら超初心者です。)先週、JavaScriptを使ったスライドショーの記事が多く読まれているので、「CSSとJavaScriptでスワイプ操作にも対応した簡単なスライドを自作する」という記事を投稿しました。自動再生と手動切り替えの違いはあるものの、似たような記事を上げても大して読まれないだろうと思っていたのですが、驚いたことに、1週間経たないうちに300人以上に読まれています。............なぜスライダーを作りたがる人がこんなに多いのか謎です。いうわけで、味を占めたぼくは需要に従い、今回はサムネイル付きのスライダーをJavaScriptで自作してみたいと思います。サムネイル付きスライダーの実行例あれこれ書く前に、まずは実行例。ネットショップの商品ページなどでよく見かけませんかね?メインとなる商品画像と、サブとなる他画像を並べておくのに使ったり。このスライダーのおおまかな仕様をまとめると下記のとおりです。class="slider">でひとまとめにしています。スライド左右に配置する矢印については、画像ファイルを用意すればulタグのbefore/after疑似要素を使って配置できるため、DIVタグで囲まなくても良いのですが.........やはり不要な画像を用意するのはPageSpeedInsightsのスコアも低くなる原因になるし、今回もCSSで矢印を描画することにしました。<DIV>~<UL>~スライド~</UL><SPAN>~矢印1~</SPAN><SPAN>~矢印2~</SPAN></DIV>みたいな入れ子構造になっています。{width:100%;object-fit:contain;padding:0;}</style>CSS部分は長いので、前回説明した部分は省略します。部分ですが、これもまぁinline-blockにしたりcursor:pointer;でマウスカーソルを変えたりといった部分はいつもどおりなので解説は不要でしょう。そのほかの部分についてちょっとだけ補足説明しておきます。LIタグの余白はfont-size:0で消せるスライド部分もサムネイル部分も、画像を横並びにするのにUL/LIタグを使っています。LIタグにdisplay:inline-block;を指定することで、横並び表示が可能になるわけですが、それだけだとどうしてもLIタグに謎の余白が出来ちゃうんですね。ように改行せずに並べて書けば消えるのですが、それではHTMLの可読性が著しく低下します。指定することで、LIタグの左右に余計な空白が入らないように調整しています。前回はそこまで細かくしなくても、ほどほどの位置にスクロールしてやればscroll-snap-typeの効果で、いい感じに吸着したので良かったのですが、今回は「サムネイルがクリックされたらスライドを適切な位置にスクロールする」という動作をJavaScriptで計算して行っているため、謎の余白が入られると困るのです。...厳密にはその謎の余白まで計算に入れれば良い話ですけど、知らない人がソースを読んだら何だろうこの謎の調整値は?と不思議に思うでしょう。いうことで、きっちりfont-size:0;を指定させてもらいました。部分でサムネイル選択時の枠線や透明度※の指定をしています。※サムネイルは50%の透明度で表示され、選択中のサムネイルだけハッキリ表示されます-webkit-optimize-contrastここで解説するようなことでもないのですが、Chromeの画像縮小処理ってデフォルトだとぼやけ気味なので、image-rendering:-webkit-optimize-contrast;を指定して、シャッキリとした縮小画像を表示するように指定しています。Safariとかだと汚くなるという話も聞くのでこのへんは好みで調整してください。題名どおり、なるべく少ないコードで済むようにしたつもりです。その分、過剰なまでにコメントを入れておいたので、おおよそはコメント読むだけでだいたいご理解頂けるかと。100);};});});</script>前回説明した矢印クリックの処理は解説を省略します。サムネイルクリック時のスライド番号の算出方法サムネイルのクリックはonclickイベントで検出するとして、問題はクリックされたサムネイルが、どのスライド番号なのかわからない点だと思います。愚直に実現するならば、クリックされたのが何番目のサムネイルなのかチェックし、その番号と同じスライドまでスクロールする、という感じでしょうか。それだとクリックするたびに毎回サムネイル全体を検索することになって無駄※な気がしたので、初期処理ですべてのサムネイルのdataset属性にサムネイル番号を割り振っておくことにしました。thumbs_no++;この部分ですね。みたいな感じでしょうか。HTMLで書くのは面倒だったし、サムネイルが増えるたびに1の次は2、2の次は3、と数えて書いていくと間違えそうだったので、プログラム側で勝手に採番することにしたわけです。参照するだけで自身のサムネイル番号がわかります。サムネイル番号さえわかれば、あとはULの横幅(=preview_ul.clientWidth)×サムネイル番号でスクロールに必要な量が算出できますよね。実は最初に作ったときはもっと複雑で、全LIタグのX座標を取得しつつ、ULタグのscrollLeftを調整していたのですが、よく考えたらスライダーのLIの横幅は全部同じなので、掛け算で良いじゃん...となりました。それぞれ横幅の違う画像を”余白なしで”数珠繋ぎにしたい、という場合はこれよりちょっとだけ複雑な計算をしなければなりませんが、長くなるので今回は省略します。先ほどはサムネイルクリック時にどのスライドまでスクロールさせるのか、という話でしたが、今回はその逆。スライドを矢印ボタン、ないしスマホのスワイプ操作でスクロールさせた場合、下に表示されているサムネイルの選択枠も変更したいな、と思ってこの機能を実装しました。スライドのスクロール時はonscrollイベントが発生するのですが、困ったことにこのイベントの発生頻度が高すぎるのです。1回スクロールする間に数十回イベントが発生するので、そのたびにサムネイル番号の判定処理を入れていたら、無駄すぎます。ここではsetTimeoutを使い、100ミリ秒後にサムネイル番号の判定処理を実行しています。なんだい100ミリ秒遅らせてるだけかい、と思うなかれ。100ミリ秒待っている間にまたonscrollイベントが発生した場合にはclearTimeoutを実行し、処理をキャンセルして、再度100ミリ秒後に処理を予約するんです。これがスクロールイベント発生時に毎回判定されるため、「スクロールイベントが100ミリ秒発生しなかった場合に限り、次の処理を行う」という処理が実現できています。スクロールが完了したよ!というイベントがあれば良いんですけどね。考えてみればどこでスクロールを終了、と判断するのかは悩ましいところですもんね。今回は100ミリ秒間、スクロールしなかったら、終了と判断しているわけですが、場合によってはもっと長い間操作しなかったときに処理したほうが良いこともあるかも知れないもの。スクロールが完了した、と判定したなら、やることはさっきの逆。現在のスクロール位置(=preview_ul.scrollLeft)をスライドの幅(=clientWidth)で割り算するだけ。scroll-snap-typeが指定されているとはいえ、スマホでの操作時など、指を離さずに画像と画像の間の中途半端な位置で動かさなければスクロール終了と判断されてしまうので、この割り算は割り切れない場合があります。その場合はMath.floorで切り捨てた値をサムネイル番号としています。動作的にはスクロール途中で指を止めたら前方のスライドのサムネイルが選択状態になる、というわけですね。これだけだとスナップ処理が動いたときにサムネイル番号がズレるケースも出てきそうなものですが、そこはありがたいことにスナップ処理が動いたときにもonscrollイベントが発生するので問題ありません。ついでに言うと、画面サイズが変わってスライドの横幅が変更されたときにすらonscrollイベントが発生します。レスポンシブデザインでも問題ないというわけ。やったね!まとめ今回は(も)jQuery等のライブラリを使わずに、サムネイル付きのスライダーを自作してみました。コメントがたくさん書いてあるから行数増えてるけれど、実質2~30行くらいのコードだし。最初、これを作ろうと思ったときはもっと複雑になる予定だったんですよ。先述の解説でも書きましたが、スライダーに表示する画像のサイズが異なるのは当たり前なので、それぞれの画像の横幅を考慮して計算しなければ...と。考えてみたら、LIタグもIMGタグもwidth:100%指定なんですよね。object-fitでうまいことその枠内に異なるサイズの画像を収めていますが、そうなるとLIタグ自体の横幅は全スライドで共通なわけです。なーんだ、それなら横幅×スライド番号でスクロール量が算出できるじゃないか、と想定していたコーディング量の半分くらいで済んでしまいました。正直なところ、なんでスライダー関係の記事がよく読まれるのか、ぼくはよくわかっていませんwぼくは趣味だからこういうのを自作するだけでキャッキャと喜べますが、業務でやるならbxsliderとかjQuery系のライブラリが充実してるので、ポイっとほおりこんで済ませちゃうと思うんですよねー。自分が趣味で運営しているサイトではjQueryは滅多に使いませんけども。重いしPageSpeedInsightsのスコアが低くなるし、なにより何かあったときに自分で書いたコードのほうが直しやすいから。同じような人がどのくらいいて、このスライダーの需要がどのくらいあるのか全くわかりませんが、もしたまたまここを訪れた方のお役に立てたのなら幸いです。関連記事JavaScriptでファイル名順に複数ファイルを読み込む方法INPUTタグで複数ファイルを読み込む際、ブラウザ内で処理するときはFileReaderオブジェクトを使うことが多いと思います。これは非同期処理なので、はてファイル名順に処理する場合はど02024-06-13JavaScriptのcanvasで縦書きを行う際の備忘録canvas上に縦書きの文章を出力して画像化しようと考えてちょっとハマったので忘れないうちにメモしておきます。結論から先に書くと、基本的にcanvasにはwriting-modeの設定が効くの02024-06-11JavaScriptのWebAudioAPIで楽曲の口パクをしてみる以前、ソフトウェアの解説動画を作った際、おっさんの声だけ流れてるのもアレだし、最近流行りのアバターにしゃべらせるやつやってみよう、と思ったことがあります。vtuberとかおじさんよくわからない02023-11-20jQuery不要なLightbox代替スクリプトLuminousが本当に軽量jQueryって...重いですよね。各種ブラウザへの対応が面倒くさかった時代には本当にありがたかったのですが、モダンブラウザ全盛の今、jQueryの必要性を感じないことが多くなってきました。前回の記事「JavaScriptで画像を連続表示してコマ撮りムービー風の表示をしてみる」では連続して画像を表示することで、コマ撮りムービーのようなものをブラウザ上に表示することに成功しました。82023-01-24JavaScriptでTABLEにソート機能を実装する(jQuery不要)jQueryもそのプラグインも、外部ライブラリも使わず、自前で書いたJavaScriptでTABLEタグをソートするプログラミング例の紹介と解説です。02:53初めまして。参考にさせていただいています。自作のサムネイル付きスライダーでサムネイルの総数を取得する方法はありますでしょうか?お手隙でご回答いただけたら幸いです。コメント投稿直後ならコメントの編集/削除が可能です。※24時間経過するか、新しく投稿した場合は古い投稿の編集や削除は出来ません。※ブラウザでCookieが受け入れられない場合はこの機能は使えません。非公開にチェックを入れたコメントは管理人のみ閲覧できます。コメント投稿のガイドライン誰もが閲覧できるコメント欄ですので個人が特定できる情報等は書き込まないようにしましょう。他人のHPやブログの文章を掲載する場合は著作権法第32条「引用」の条件を満たすかご確認ください。誹謗中傷にあたる表現などは場合によっては法的な責任を問われる可能性があるためご注意ください。とっちらか~るTOP。