Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding paging controls to a full page touch swiper/slider - Hammer.js

CLICK FOR FIDDLE

Below is a fully functional full page touch slider I have created using hammer.js

You can drag, swipe or pan to navigate between pages.

The slider works as expected but I am now trying to create fallback navigation by adding two buttons so paging left and right can occur on click also.


QUESTION

How can the hammer swipe left or right be called on click? (Javascript or jQuery).

CURRENT ATTEMPT

$('#Left').on('click', function() {
  HammerCarousel(document.querySelector('.Swiper'), 'Left');
});

FULL CODE

function swipe() {
  var reqAnimationFrame = (function () {
    return window[Hammer.prefixed(window, "requestAnimationFrame")] || function (callback) {
      setTimeout(callback, 1000 / 60);
    }
  })();

  function dirProp(direction, hProp, vProp) {
    return (direction & Hammer.DIRECTION_HORIZONTAL) ? hProp : vProp
  }

  function HammerCarousel(container, direction) {
    this.container = container;
    this.direction = direction;
    this.panes = Array.prototype.slice.call(this.container.children, 0);
    this.containerSize = this.container[dirProp(direction, 'offsetWidth', 'offsetHeight')];
    this.currentIndex = 0;
    this.hammer = new Hammer.Manager(this.container);
    this.hammer.add(new Hammer.Pan({ direction: this.direction, threshold: 10 }));
    this.hammer.on("panstart panmove panend pancancel", Hammer.bindFn(this.onPan, this));
    this.show(this.currentIndex);
  }

  HammerCarousel.prototype = {
    show: function (showIndex, percent, animate) {
      showIndex = Math.max(0, Math.min(showIndex, this.panes.length - 1));
      percent = percent || 0;

      var className = this.container.className;
      if (animate) {
        if (className.indexOf('animate') === -1) {
          this.container.className += ' animate';
        }
      } else {
        if (className.indexOf('animate') !== -1) {
          this.container.className = className.replace('animate', '').trim();
        }
      }

      var paneIndex, pos, translate;        
      for (paneIndex = 0; paneIndex < this.panes.length; paneIndex++) {
        pos = (this.containerSize / 100) * (((paneIndex - showIndex) * 100) + percent);
        translate = 'translate3d(' + pos + 'px, 0, 0)';
        this.panes[paneIndex].style.transform = translate;
        this.panes[paneIndex].style.mozTransform = translate;
        this.panes[paneIndex].style.webkitTransform = translate;
      }
      this.currentIndex = showIndex;
    },

    onPan: function (ev) {
      var delta = dirProp(this.direction, ev.deltaX, ev.deltaY),
          percent = (100 / this.containerSize) * delta,
          animate = false;
      if (ev.type == 'panend' || ev.type == 'pancancel') {
        if (Math.abs(percent) > 20 && ev.type == 'panend') {
          this.currentIndex += (percent < 0) ? 1 : -1;
        }
        percent = 0;
        animate = true;
      }
      this.show(this.currentIndex, percent, animate);
    }
  };
    
  var outer = new HammerCarousel(document.querySelector('.Swiper'), Hammer.DIRECTION_HORIZONTAL);
};

$(swipe);
html,
body,
.Page,
.Swiper{
  position:relative;
  height:100%;
}
.Swiper{
  background:#666;
  overflow:hidden;
}
.Swiper.animate > .Page{
  transition:all .3s;
  -webkit-transition:all .3s;
}
.Page{
  position:absolute;
  top:0;
  left:0;
  height:100%;
  width:100%;
  padding:0 10px;
  font:42px Arial;
  color:#fff;
   padding-top:10%;
  text-align:center;
}
.Page:nth-child(odd) {
    background:#b00;
}
.Page:nth-child(even) {
    background:#58c;
}
#Left,
#Right{
    position:absolute;
    top:0;
    height:50px;
    width:50px;
    background:#fff;
    text-align:center;
    font:16px/3em Arial;
    cursor:pointer;
}
#Left{
    left:0;
}
#Right{
    right:0;
}
<script src="http://hammerjs.github.io/dist/hammer.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="Swiper">
    <div class="Page">PAGE 1<br/>DRAG LEFT</div>
    <div class="Page">PAGE 2<br/>SWIPE ME</div>
    <div class="Page">PAGE 3<br/>HOLD TO PAN</div>
    <div class="Page">PAGE 4<br/>FLICK TO GO BACK</div>
</div>

<div id="Left">Left</div>
<div id="Right">Right</div>
like image 517
DreamTeK Avatar asked Mar 04 '15 15:03

DreamTeK


1 Answers

I have crafted a jQuery solution for this that should satisfy the fallback you are looking for.

Some things to consider, though. In your example as well, page re-size is not accounted for. I have not done so in this either to remain consistent and solve the immediate issue, but you will notice I am grabbing the $('.Page').width(); as a variable in this solution. I would recommend re-assigning this value if you do account for re-sizing. Also, a mix of swiping/clicking will throw this off. I assume since you indicated this will be a fallback, the user will receive one of the two experiences. If not, we'll need a way to update tracker on swipe events as well.

You'll notice var tracker = { 'R': 0 }. While naming may not be the best, 'R' will account for how many right "swipes" (navigation clicks) the user has performed in a plus/minus 1 manner

<div id="Left" direction="L">Left</div>
<div id="Right" direction="R">Right</div> 

$(function() {
    var width = $('.Page').width();
    var pages = $('.Page').length;
    var tracker = { 'R': 0 }

    $('#Right, #Left').click(function() {

        $(this).attr('direction') === 'R' ? 
            ((tracker.R < (pages - 1) ? tracker.R += 1 : pages)) : 
            (tracker.R > 0) ? (tracker.R -= 1) : 0;

        $('.Swiper').animate({ 'scrollLeft': $('.Page').width() * tracker.R  }, 250)
    });
});

JSFiddle Link

like image 177
scniro Avatar answered Oct 10 '22 19:10

scniro