レスポンシブでシンプルなイメージスライダーを作ってみる

2015-02-28

配布レベルに調整したものを以下で公開していますのでどうぞ!

https://studio-key.com/jquery-image-slider/

 

 

画像をスライドするイメージスライダーがたくさん公開されていて、どれも素晴らしいものばかりです。CMSだとプラグインも豊富ですし導入も簡単ですが、これが仕事となるとそうもいきません。例えばコーディングだけを依頼されるケースです。Illustratorで作成したデザインを頂き、それを起こすケースで「ここはスライダー使って下さい」と指示されると、それは自分で組み込む事になります。

そこで色々とプラグインを探す事になるのですが、どれも高機能だったり余計な機能が多くてカスタマイズが大変であったりなど、なかなかシンプルなものが手に入りません。あと、シンプル過ぎてレスポンシブで無かったりなど。あとプライドが許さなかったりとか(違

じゃあまぁ自作しましょう!、という事で作ってみます。

先ずはコンセプト

・スタイルシートを別途にロードしないこと。必要なものは極力シンプルに。
・画像を配置する箇所に面倒なHTMLタグを極力書かないこと。
・レスポンシブに対応させる。
・ある程度の要求に耐えられるよう、左右移動アイコン、ページングアイコン、サムネイルアイコンは実装する。
・タブレットやスマートフォンでは指でスライドさせられること。
・WordPressの記事投稿欄などにも使えること※但しテキストモード。 こんな感じ

面倒なのでやらないもの

・画像のローディングアクション※後述
・無限スライド。ラストまで行くと1枚目に戻るタイプにする。
・サムネールとか左右アイコンをクリックしたらスライドアニメーションを停止して再開しない(これはとても面倒)
・旧IEとか無視、7すら旧OSになりつつある現在、XPはもうスルーで。

画像のローディングアクションと画像サイズについて

理想は画像を全て読み込んだらスライダーを開始するという処理をスライダープラグインに組み込めば良いのですが、そもそも、レスポンシブ=スマートフォンの細い回線で閲覧するという事なので、パソコンでは楽々表示出来るサイズの画像でも、スマフォだと重いのです。私的に、画像が大きくなりがちなスライダーをスマートフォンでレスポンシブに対応させる事に無理があると思っています。ましてMVMOな方は通信量に制限がありますし。

私が実装するならば、PC用とモバイル用の軽量な画像を用意し、展開する画像自体を入れ替えます。

また、そもそもスライダーだけに限らず、ページ自体がデータベースを使うなど多様化して処理に負荷が掛かる現在のホームページにおいて、格安サーバーのおもた~~いDBでCMS動かしつつ、画面全体に展開される激重画像をスライドさせるなんて無理があるのです。スライダーはローディングアクションを終えて表示を開始しても、その他のコンテンツが未表示、なんて事になっては意味が有りません。

なので、スライダーを使うなら相応の大きさにし、画像も色数を減らした画像で低画質jpgでも劣化しない画像を作成するなど、工夫が必要だと思います。そして、スライダーにではなく、ページ自体にローディングを導入する方が無難だと思います。

という言い訳をしつつ、今回作るスライダーには画像ローディングは入れてません。

サンプル各種

前置き長くなりましたが、先ずはサンプルを見て下さい。あ、それと、あえて重たい画像を使うので、サンプル1は前述したページ全体をローディングするものを組み込んでいますサンプル1以外から見ると、画像がキャシュされてませんので、とっても重たいと思われます。

SAMPLE 1 基本的な設定

SAMPLE 2 効果を付ける

SAMPLE 3 スライドさせない

SAMPLE 4 メッセージを表示

とりあえず設置方法

これ(js)をページに読み込みます。 jQueryは読み込んでる前提です。

スライダーの枠とレスポンシブのCSSを書く

こればかりは書かないとなりませんので、書きます。名称は何でもいいので表示したい部分に合わせてどうぞ。

#mySlider{
	width: 800px;
  height: 600px;
  overflow: hidden;
}
@media screen and (max-width: 800px){
  #mySlider{
    width: 100%;
  }
}

 

↑で作った枠に画像を配置します。

画像の幅とかaltとか除外してますが、あっても構いません。

  <div id="mySlider">
    <a href="#"><img src="images/01.jpg" /></a>
    <a href="#"><img src="images/02.jpg" /></a>
    <a href="#"><img src="images/03.jpg" /></a>
    <a href="#"><img src="images/04.jpg" /></a>
    <a href="#"><img src="images/05.jpg" /></a>
  </div>
jsを書く

一番シンプルな書き方です。#mySlider の部分は作った枠の名前にして下さい。WordPressだと $ ダメなのでjQueryなどに置き換えて下さい。

 $(function(){
    $('#mySlider').mySlider();
 });

 

これだけです。

あ、でも画像は全て同じサイズで有ることが前提ですのでご注意を。同じサイズであれば、作った枠の中に適当に書いておいて下さい。あと勝手にスタイルとかjsが設定して勝手にスライドしてくれます。

但し、メッセージを出す場合はちょっと設定が必要です。

サムネイルを出す

元画像を使う方法に変更

data-img=”images/01_s.jpg”

サムネイルに大きな画像を無理やり小さくして表示しても微妙なので、別にサムネイル用の画像を作ってそれを設定します。サイズは幅50px程度にでも。ただ、モバイルだと幅が狭いのでサムネイル一杯あると落っこちます。3~4枚程度なら良いですが、数が多いならサムネイルはオフの方が良いかもです。

メッセージを出す

  <div id="mySlider">
    <a href="#"><img src="images/01.jpg" data-img="images/01_s.jpg" alt=""/></a>
    <a href="foo2.html"><img src="images/02.jpg" data-img="images/02_s.jpg" alt=""/></a>
    <a href="foo3.html"><img src="images/03.jpg" data-img="images/03_s.jpg" alt=""/></a>
    <a href="foo4.html"><img src="images/04.jpg" data-img="images/04_s.jpg" alt=""/></a>
    <a href="foo5.html"><img src="images/05.jpg" data-img="images/05_s.jpg" alt=""/></a>
    
    <!-- message 0から始まる事に注意 [mySlider_message]は変更不可 -->
      <div class="mySlider_message" data-num="0">
        <div style="text-align:center">Message Sample1</div>
      </div>
      <div class="mySlider_message" data-num="1">
        <div style="text-align:center">
        <div style="text-align:center">
          <h2 style="margin: 5px;">DESGINED BY STUDIO KEY</h2>
          HTMLでもOK
        </div>
        </div>
      </div>
      <div class="mySlider_message" data-num="2">
        <div style="text-align:center">
          <div id="imgtest"></div>
          画像は100%表示になるのでCSSで背景画像にする
        </div>
      </div>
      <div class="mySlider_message" data-num="3">
        <div style="text-align:center">Message Sample4</div>
      </div>
      <div class="mySlider_message" data-num="4">
        <div style="text-align:center">Message Sample5</div>
      </div>
  </div>

<div class=”mySlider_message” data-num=”0~画像枚数分”>

こんな感じでHTMLで書きます。0から始める事にご注意を。

オプションに関して

     //スライダー設定 -------------------------
      ,'slider'     : true  //有効(true) 無効(false)
      ,'imgmove'    : 1000  //画像スライドのスピード
      ,'delay'      : 5000  //次の画像へスライドする待機時間
      ,'start'      : 1000  //スライダー開始遅延

     //●アイコン設定 -------------------------
      ,'paging'    : false     //有効(true) 無効(false)
      ,'page_def'  : '#DDDDDD' //デフォルトの色
      ,'page_this' : 'pink'    //現在の色
      
     //左右アイコン設定 -------------------------
      ,'controll'  : false     //有効(true) 無効(false)
      ,'cnt_bg'    : '#000000' //背景色
      ,'cnt_cr'    : '#FFFFFF'    //文字色
      
     //サムネイル -------------------------------
      ,'thumbnail'   : false     //有効(true) 無効(false)
      ,'thm_opacity' : '0.40'    //画像の透明度
      ,'thm_bg'      : '#000000' //サムネイル枠の背景色
      
     //メッセージ -------------------------------
      ,'message'   : false     //有効(true) 無効(false)
      ,'msg_bg'    : '#000000' //背景色
      ,'msg_cr'    : '#FFFFFF'    //文字色

色々とあるのでお試しを。サンプルのコードのように、jsの編集ではなくHTML側で設定出来ます。必要なものを書き加えて下さい。

ここからはお勉強

作って見ると言いつつ設置方法ばかり書いていますが、ここからはカスタマイズしたいとか自作してみたいといった方向けに書いていきます。稚拙なjsコードですが、参考になれば。

画像スライドの仕組みを考えてみる

以前もそんなエントリーを書いていますが、仕組みとしては以下のようになります。

・スライドする部分を囲う枠は高さ、幅を固定し、overflow: hidden(はみ出した部分は隠れる)を指定+position:relative;
・その中にスライドする枠をposition:absolute(絶対位置)で配置し、横幅を全画像の幅を足した数値にする。
・これで画像は横並びになる。
・後は左からの距離を少しづつマイナスしていくコードを書けば動く(スライドする)

そんな感じのシンプルなサンプル

$(function () {
  var i=0;
  var timerId = setInterval(function() {
    i++;
    if(i>=3) i=0;
    image_move(i);
  },5000);
  
  function image_move(n){
    var move = n*400;
    $("#mySlider #move").stop().animate({left:'-'+move+'px'},{ duration: 1000, easing: 'swing', } );
  }
});

これで基本的なスライドが出来ます。画像の幅は400pxが3枚なので、枠の幅を1,200px(以上)で作り、後は400px,800px,1,200pxと移動し、0に戻すだけですね。

ページャーとか左右のアイコンとか付けないなら、もうこれで十分だと思われます。

レスポンシブの考え方

そもそもスライダーでレスポンシブといっても、やることはjsじゃなくCSS側です。

#sample{
	width:900px;
}
#sample img{
	width:100%;
	height:auto;
}
@media screen and (max-width: 800px){
  #sample{
    width: 100%;
  }
}

例えばこんなコードを書けば、<div id=”sample” …… はブラウザの幅が800px以下になれば、幅は100%なります。また、そこに含まれる画像は、元幅がなんであれ#sampleの幅一杯に表示されます(高さはオート)

なので、スライダーの枠をこのように可変にし、スマフォやタブレットに対応させれば対応出来そうですが

ダメなんですね。

幅が可変する=スライドする距離も変わるという事になります。いえ、多分そうだと思われます。人のコード見る前に先ず作ってみるタイプなので、良い方法があれば・・・

という事で、スマフォを縦持ち、横持ちにしたときはスライド幅も可変させる必要が有ります。

初期設定しておいた幅や高さを書き換える
/***********************************
 * ウインドサイズが変更された時の処理
 ***********************************/
    var changeWidowSize = function(obj){
        var w =$(obj).width();              //.mySliderの幅
        var h =$(obj).find('img').height(); //画像の高さ
      //settingに設定
        setting.slider_w = w;
        setting.slider_h = h;
        
        if(setting.thumbnail === true){ //myslider_thumbnail
          var thm_w = setting.slider_w - 20;
          $("#myslider_thumbnail").width(thm_w);
        }

       changeImageSize(obj);
    };
書き換えた数値で各要素を再定義する
/***********************************
 * スタイルの設定など
 ***********************************/
  //枠内の画像の幅と高さを可変
  //高さ、幅を完全に捕捉するのは難しいのでウインドサイズ変更時は多少の誤差は出る
    var changeImageSize = function(obj){
      
      //スライダーのスタイルを設定する *高さは画像の高さにする
        $(obj).css({
           'margin-right' : 'auto'
          ,'margin-left'  : 'auto'
          ,'position'     : 'relative'
          ,'height'       : setting.slider_h+'px'
        });
        
      //imgとA要素をsettingに設定
        setting.img_list = $(obj).find('img');
        setting.href_list = $(obj).find('a');

      //枠内のLIタグのスタイルを設定 絶対位置にして高さと幅を設定値にする
        $(obj).find('li').css({
           'list-style' : 'none'
          ,'float'      : 'left'
          ,'height'     : setting.slider_h+'px'
          ,'width'      : setting.slider_w+'px'
        });
        
      //サムネイル画像は半透明に
        $("#myslider_thumbnail img").css({
           '-moz-opacity':setting.thm_opacity
          ,'opacity':setting.thm_opacity
        });
        $("#myslider_thumbnailimg0").css({ //1枚目は透明度無しにする
           '-moz-opacity':'1'
          ,'opacity':'1'
        });
        
      //枠内の画像は幅に合わせて可変させる
        $(obj).find('img').css({
           'width'  : '100%'
          ,'height' : 'auto'
        });
    };

但し、ブラウザの幅を乱暴に変えると当然不具合が出ます。2~3回動けば正常に戻りますけど、これは仕方ないなぁと思います。そもそもモバイルは縦にするか横にするか程度でしょうから。

アイコンとかサムネールとかの処理

スライダー部分は以下のようになっています。

/***********************************
 * スライダー処理
 ***********************************/
    var startSlide = function(obj,i){
      timerId = setInterval(function() {
        if(i > (imgLen-2)) i=-1;
        getMove(obj,i);
        i++;
      },setting.delay);
    };

この関数に画像の番号を渡すとスライド処理を行う仕組みです。オートスライダーの場合はこの数値を自動で次の画像(前の画像)へ移動するように計算して渡していますが、ページャーアイコンとかサムネールとかは、それそのものにその番号を最初に割り振っておき、クリックしたときにその数値をスライダー関数に渡すだけです。

で、本来はここでディレイを作り、アニメーションを再開したいとこなのですが、これがちょっと面倒なのです。要はアニメーションのキューを開放し、再始動させるのですが、どのみちクリックした時点で注視したいのでしょうから、それ以上アニメーションシなくても良いかなと思い、停止させています。

コード全部を説明してるともっと良い構文があるんじゃないかとか悩みだすので、このくらいにしておきます。書いてる中盤でインラインで書いてるCSSとか$(‘head’).appendすりゃ良かったなぁとか後悔してますので。

これは出来るかどうかの試行なので、整理してから正式リリースしようかなぁと思ってます。