带触摸打孔的JQuery Draggable停止垂直滚动

时间:2016-11-25 07:11:12

标签: javascript jquery html css

我正在使用JQuery Draggable函数和Touch Punch来生成可以通过单击和拖动滚动的水平滑块列表。它在触摸和点击设备上运行良好。我面临的问题是,如果我尝试在触摸设备中向上或向下滚动,它就无法正常工作。

我查看了SO并发现删除" event.preventDefault"从TouchPunch允许垂直滚动,这个修复的问题是,它只适用于某些设备,而不是全部。

我想知道是否有人有任何其他解决方案,或者生成同样适用于触摸和点击事件的相同水平滑块的替代方法。

以下是示例代码(JQuery Draggable):



$(function() {
  var slides = $('#list1 ul').children().length;
  var slideWidth = $('#list1').width();
  var min = 0;
  var max = -((slides - 1) * slideWidth);

  $("#list1 ul").width(slides * slideWidth).draggable({
    axis: 'x',
    drag: function(event, ui) {
      if (ui.position.left > min) ui.position.left = min;
      if (ui.position.left < max) ui.position.left = max;
    }
  });

    $("#list2 ul").width(slides * slideWidth).draggable({
    axis: 'x',
    drag: function(event, ui) {
      if (ui.position.left > min) ui.position.left = min;
      if (ui.position.left < max) ui.position.left = max;
    }
  });


});
&#13;
#list1 {
  position: relative;
  height: 16em;
  width: 100%;
  text-align: middle;
  white-space: nowrap;
  overflow-x: hidden;
  overflow-y: hidden;
}

#list1 .floating-box {
  margin: auto;
  display: inline-block;
  width: 15em;
  height: 13.5em;
  margin: 0.1em;
  border: 0.2em solid black;
  background-color: white;
}

#list2 {
  position: relative;
  height: 16em;
  width: 100%;
  text-align: middle;
  white-space: nowrap;
  overflow-x: hidden;
  overflow-y: hidden;
}

#lis2 .floating-box {
  margin: auto;
  display: inline-block;
  width: 15em;
  height: 13.5em;
  margin: 0.1em;
  border: 0.2em solid black;
  background-color: white;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="list1">
    <ul>
    <p>One</p>
    <div class="floating-box">Floating box</div>
    <div class="floating-box">Floating box</div>
    <div class="floating-box">Floating box</div>
    </ul>
 </div>


  <div id="list2">
    <ul>
     <p>Two</p>
     <div class="floating-box">Floating box</div>
     <div class="floating-box">Floating box</div>
     <div class="floating-box">Floating box</div>
    </ul>
  </div>
&#13;
&#13;
&#13;

如果我触摸list1或list2 div并尝试向上或向下滚动,则它不会识别该移动。任何帮助或指示将不胜感激。

2 个答案:

答案 0 :(得分:4)

修改
基于根据pageY的{​​{1}}属性确定划线方向的想法。

从长远来看,我认为避免烦人的双击(见下面的第一个答案)是一个好主意。
它仍有妥协,但它更合理。

我做了很多事情......我得到的最好结果就是当我放弃模拟touchemove上的滚动时。

以下是我现在使用三个触摸事件中的每一个的方法:

  • touchstart 获取初始变量,例如:window scrollTop和pageY。

  • touchmove 确定滑动方向并获取最后一页Y.

  • touchend 进行数学计算,以确定页面应该滚动。
    为了可爱,我将结果值放在touchmove中 令我惊喜的是,它确实非常顺利地补偿了页面仅在.animate()上滚动的事实。
    我认为很少有用户会注意到它;)。

自&#34; Touch-Punch&#34;默认情况下正在进行水平滑动,&#34;妥协&#34;只会影响垂直滚动。



这是代码:
live link在启用touche的设备上试用它。

touchend

<小时/>

第一个答案,使用&#34;双击&#34;切换方向。

首先,Touch Punch网站声称它基本上是一个jQuery-UI hack 来处理实际上未被jQuery-UI处理的一些案例...... 并且可以找到Touch Punch失败的情况。

您的问题已向Touch Punch开发人员here报告 作为对(在我这里的话)的回答,他们说它不是真的错误或问题......
但用法&#34;冲突&#34;在两个不同的&#34;希望&#34;使用相同触摸事件的动作 有时滚动页面,有时拖动元素。

作为解决方案提示,他们发布了this Fiddle 它建议找到一种在需要时禁用可拖动的方法。

但在此解决方案中,可滚动部分可拖动元素中 哪不是你的情况。
并且您几乎可以将所有移动屏幕空间用于可拖动元素,因此不会留下任何空间来触发$(function() { var slides = $('#list1 ul').children().length; var slideWidth = $('#list1').width(); var min = 0; var max = -((slides - 1) * slideWidth); $(".draggable").width(slides * slideWidth).draggable({ axis: 'x', drag: function(event, ui) { if (ui.position.left > min) ui.position.left = min; if (ui.position.left < max) ui.position.left = max; } }); var startTouchX=0; var startTouchY=0; var actualPosX; var actualPosY; var eventCounter=0; var directionDetermined=false; var direction; var thisTouchX; var thisTouchY; var lastTouchY; $(document).on("touchstart", function(e) { // Actual document position actualPosX = $(document).scrollLeft(); actualPosY = $(document).scrollTop(); // StartTouches startTouchX = parseInt(e.originalEvent.touches[0].pageX); startTouchY = parseInt(e.originalEvent.touches[0].pageY); }); $(document).on("touchmove", function(e) { // Arbitrary considering ONLY the fourth event... // Touchmove fires way too many times! // We only need to determine the main direction ONCE. // This prevents an "s" swipe from messing this code. eventCounter++; if(eventCounter==4 && !directionDetermined){ thisTouchX = parseInt(e.originalEvent.touches[0].pageX); thisTouchY = parseInt(e.originalEvent.touches[0].pageY); if ( (Math.abs(thisTouchX - startTouchX)) / Math.abs(thisTouchY - startTouchY) > 1){ //check swipe direction // HORIZONTAL $("#debug").html("HORIZONTAL"); directionDetermined=true; // NO NEED here. This is re-enabled on touchend, if it has been disabled. //$(".draggable").draggable('enable'); } else{ // VERTICAL $("#debug").html("VERTICAL"); directionDetermined=true; direction="vertical"; $(".draggable").draggable('disable'); // Disable draggable. } } // Getting all the Y touches... // The "last" value will be used on touchend. lastTouchY = parseInt(e.originalEvent.touches[0].pageY); //$("#debug").html(lastTouchY); }); $(document).on("touchend", function(e) { if(direction=="vertical"){ //$("#debug").html(lastTouchY); var thisMoveY = -parseInt(lastTouchY - startTouchY); //$("#debug").html(thisMoveY); var newPosY = (actualPosY + thisMoveY); //$("#debug").html(actualPosX+ " " +newPosY); //window.scrollTo(actualPosX, newPosY); $("html,body").animate({ scrollTop: newPosY },400); } // Reset everything for a future swipe. startTouchX=0; startTouchY=0; eventCounter=0; directionDetermined=false; direction=""; $("#debug").html(""); // Re-enable draggable. $(".draggable").draggable('enable'); }); }); 周围的空间。

所以...我有这个想法,我希望能有所帮助。

如果您找到一种优雅的方式告知您的用户&#34;双击&#34;该怎么办?改变运动方向。
在这里,我建议一个非常简单的双箭头&#34;显示运动方向。
也许你会找到更好的东西。

这肯定是一个有点妥协的用户体验,要求他们双击...
但如果您的布局真的需要它,也许它没问题。

所以在这里,我复制了你的initial issue 这是the fix that I suggest

我只在三星Galaxy S3上试过它,但应该可以在每个触控设备上使用。

draggable("disable")

请注意,它使用Hammer.jsCDN)来检测双击。

double arrow的一些额外CSS。

$(function() {
    var slides = $('#list1 ul').children().length;
    var slideWidth = $('#list1').width();
    var min = 0;
    var max = -((slides - 1) * slideWidth);

    $(".draggable").width(slides * slideWidth).draggable({
        axis: 'x',
        drag: function(event, ui) {
            if (ui.position.left > min) ui.position.left = min;
            if (ui.position.left < max) ui.position.left = max;
        }
    });

    // Flag
    var draggableEnabled=true;

    // Find the doubletap position (to show a nice double arrow)
    var tapPosition=[];
    $(document).on("touchstart",function(e){
        tapPosition[0] = parseInt(e.touches[0].pageX) - $(document).scrollLeft() - ($("#arrows img").width()/2);
        tapPosition[1] = parseInt(e.touches[0].pageY) - $(document).scrollTop() - ($("#arrows img").width()/2);
    });

    Hammer(document).on("doubletap", function() {
        //alert("Double tap");
        draggableEnabled = !draggableEnabled;   // Toggle

        if(!draggableEnabled){
            $(".draggable").draggable('disable');   // Disables draggable (and touch Punch)
            $("#arrows img").css({
                    "transform":"rotate(90deg)",    // Nice vertical double arrow
                    "top":tapPosition[1],
                    left:tapPosition[0]
                }).fadeIn(600, function(){
                $(this).fadeOut(600);
            });

        }else{
            $(".draggable").draggable('enable');    // Enables draggable (and touch Punch)
            $("#arrows img").css({
                    "transform":"rotate(0deg)",     // Nice horizontal double arrow
                    "top":tapPosition[1],
                    left:tapPosition[0]
                }).fadeIn(600, function(){
                $(this).fadeOut(600);
            });
        }
    }); 
});

答案 1 :(得分:0)

这是我最接近它的,我想知道是否有人可以改进这段代码:

$(watchlist).on("touchstart", function(e) {
        touchY = e.originalEvent.touches[0].pageY;
        touchX = e.originalEvent.touches[0].pageX;

    });

    $(watchlist).on("touchmove", function(e) {

        var fTouchY = e.originalEvent.touches[0].pageY;
        var fTouchX = e.originalEvent.touches[0].pageX;

        if ((Math.abs(fTouchX - touchX)) / Math.abs(fTouchY - touchY) > 1){ //check swipe direction

            $("#watchlist ul").draggable( 'enable'); //if swipe is horizontal
        }
        else{
            $("#watchlist ul").draggable( 'disable'); //if swipe is horizontal
        }


    });

此代码存在的问题是,只有在触摸移动完成后才停用可拖动功能。如果任何人都可以修改此代码,以便在条件满足期间停用可拖动功能,则在touchmove期间,而不是之后,我会给予他们赏金。