为全页面触摸滑块(Hammer.js)添加分页控件

8

点击获取FIDDLE

下面是我使用hammer.js创建的全屏触摸滑块,您可以通过拖动滑动平移来浏览页面。

滑块的功能正常,但现在我正在尝试通过添加两个按钮创建回退导航,以便也可以通过单击进行向左和向右翻页。


问题

如何在单击时调用hammer左滑或右滑?(Javascript或jQuery)。

当前尝试

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

完整代码

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>

1个回答

2
我已经为此制作了一个 jQuery 解决方案,应该满足您所需的回退功能。
但是需要考虑一些事情。在您的示例中,页面重新调整大小也没有被考虑进去。在这个解决方案中我也没有考虑到,以保持一致并解决直接问题,但您会注意到我在此解决方案中将 $('.Page').width(); 作为变量进行了获取。如果您考虑重新调整大小,我建议重新分配这个值。此外,滑动/点击的混合使用也会导致这种情况出现。我“假设”由于您指示这将是一个回退,用户将接收两个体验中的其中之一。如果不是这样的话,我们还需要一种方法来在滑动事件上更新 tracker
您会注意到 var tracker = {'R': 0}。虽然命名可能不是最好的,但 'R' 将考虑用户已经执行的右侧“划动”(导航点击)的数量,并以加/减 1 的方式进行计算。
<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


是的,这个方案可行且不错,但它并不能完全满足我的需求。按钮只是备用选项,但它们将同时可见,我无法保证用户不会尝试同时使用滑动和点击的组合。我真的认为可以很容易地通过 onclick 调用来激活左 / 右动画。 - DreamTeK
我建议在你的滑动回调中将Tracker更新为全局变量,或者找到一种不向用户呈现两种体验的方法。能力检测?现在跟踪器的记录应该不难了。你能在成功滑动时触发代码吗?@Obsidian - scniro
谢谢@sal niro,我会跟进这个。感谢您的建议,做得好。 - DreamTeK
@Obsidian,你在这方面有进展吗?我很好奇。我看到你已经授予了赏金,如果你认为答案令人满意,你是否愿意接受它? - scniro
我当然很抱歉。感谢您在此事上的帮助。 - DreamTeK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接