読者です 読者をやめる 読者になる 読者になる

みかづきブログ その3

3ヶ月つづけてみました。

スマフォ用軽量カルーセルをつくろう その3

kimizuka.hatenablog.com
kimizuka.hatenablog.com

以前つくったもの を改良しました。

  1. 自動送りとユーザー操作のタイミングが重なったときの対策をいれました。
  2. touchend が発火しないことのあるAndroid にも対応させるべく、touchmoveにイベントを張りました。

kimizuka.hatenablog.com


DEMO


※ スマートフォンでしか動作しません


JavaScript

// forked from kimmy's "forked: カルーセルをつくろう" http://jsdo.it/kimmy/7siJ
// forked from kimmy's "カルーセルをつくろう" http://jsdo.it/kimmy/w9Gt
(function buildCarousel(win, doc, $) {
 
  "use strict";
 
  function Carousel($elm) {
    var that  = this,
        diff  = 0,
        x     = 0,
        LIMIT = 100;
 
    that.$elm     = $elm;
    that.$photos  = $elm.find(".photos"),
    that.$photo   = $elm.find(".photo"),
    that.$btn     = $elm.find(".btn"),
    that.index    = $elm.attr("data-carousel") - 0 || 0;
    that.length   = $elm.find(".photo").length;
    that.max      = that.length - 1;
    that.timer    = null;
    that.INTERVAL = 5000;
      
    $elm.on("touchstart", _start);
    $elm.on("touchmove", _move); // endからmoveに変更 ※ Android対策
 
    that.$photos.prepend(that.$photo.last().clone());
    that.$photos.append(that.$photo.eq(0).clone());

    // コピーしたDOM分調整
    that.index  += 1;
    that.length += 2;
    that.max    += 2;
      
    that.$photos.width(that.length * 100 + "%");
    $elm.find(".photo").width(100 / that.length + "%");

    that._show();
 
    function _start(evt) {
      x = evt.originalEvent.touches[0].pageX;
    }
 
    function _move(evt) {
      diff = x - evt.originalEvent.changedTouches[0].pageX;
 
      if (diff > LIMIT) {
        x = evt.originalEvent.changedTouches[0].pageX;
        that.next();
      } else if (diff < -LIMIT) {
        x = evt.originalEvent.changedTouches[0].pageX;
        that.prev();
      }
    }
  }

  Carousel.prototype._show = function() {
    var that = this;

    that.$photos.stop(true).animate({
      left : that.index * -100 + "%"
    }, function() {
      if (that.index <= 0) { // タイミング悪く負の値になったとき対策で = から <= に変更
          that.index = that.max - 1;
      } else if (that.index >= that.max) { // タイミング悪くmaxを越えたとき対策で = から >= に変更
          that.index = 1;
      }

      that.$photos.css({
        left : that.index * -100 + "%"
      });
        
      that.$elm.attr("data-carousel", that.index);
    });

    if (that.length > 1) {
      clearInterval(that.timer);
      that.timer = setTimeout(that.next.bind(that), that.INTERVAL);
    }
  };

  Carousel.prototype.next = function() {
    var that = this;

    if (that.length < 2) {
      return;
    } 

    ++that.index;

    that._show();
  };

  Carousel.prototype.prev = function() {
    var that = this;
 
    if (that.length < 2) {
      return;
    }

    --that.index;

    that._show();
  };
 
  $(function() {
    var $carousel = $("[data-carousel]");
   
    $carousel.each(function(index) {
      new Carousel($carousel.eq(index));
    });
  });
 
})(this, document, jQuery);