首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >水平拖动会阻塞页面的默认垂直滚动。

水平拖动会阻塞页面的默认垂直滚动。
EN

Stack Overflow用户
提问于 2015-06-24 10:30:43
回答 2查看 2.2K关注 0票数 2

我已经创建了一个码页来描述我想要达到的目标。

我正在创建一个时间线概述与几个水平拖放项目。除了jqueryjquery-ui之外,我还使用jquery-ui-touch-punch使移动设备上的所有手势成为可能。在桌面上,一切都很好,但在移动设备上就不行了。

不幸的是,$(".timeLineItemContainer").draggable({ ... });极具侵略性,它还吞噬了我的垂直滚动行为,导致当我触摸其中的1项时,无法在移动上向下滚动

不知何故,我需要启用或禁用一个项目的拖动能力,这取决于我的滚动操作的方向。当我在event.preventDefault();中禁用jquery-ui-touch-punch.js时,它会向下滚动,只有这样,clickhorizontal move才不能正常工作(移动设备上的水平滑动指的是history.goback,因为我需要history.goback作为手势)。

总结一下:我想要的只是防止默认行为,除了垂直滚动。

对如何实现这一点有任何想法吗?或是否有任何其他想法/方法来实现这一目标?

以下是移动版本的链接

(只是多个项目的简单列表)

代码语言:javascript
复制
        <div class="timeLineItemContainer">
        <div class="subItemMiddleContainer">
            <div class="timeLineHeader">
                <div>
                    <span>A TITLE</span>
                </div>
                <div>
                    <div>Some other text text</div>
                </div>
            </div>
        </div>
        <div class="subItemBottomContainer">
            <ul>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="info">Thu 12 March</span>
                    </div>
                </li>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">some additional text</span>
                        <span class="info time strikethrough">bla</span>
                        <div class="info time attention">
                            <span>yup</span>
                        </div>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">Text</span>
                        <span class="info">content</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">title</span>
                        <span class="info">value</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">Another title</span>
                        <span class="info">another value</span>
                    </div>
                </li>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">always visible</span>
                        <span class="info time strikethrough">just because</span>
                        <div class="info attention">
                            <span>attention!</span>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
    </div>
    <div class="timeLineItemContainer">
        <div class="subItemMiddleContainer">
            <div class="timeLineLeft">
                <div class="timeLinePipe"></div>
            </div>
            <div class="timeLineHeader">
                <div>
                    <span>Some other text</span>
                </div>
                <div>
                    <div>Ola!</div>
                </div>
            </div>
        </div>
        <div class="subItemBottomContainer">
            <ul>

                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="info">A date</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">label</span>
                        <span class="info">value</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">anotehr label</span>
                        <span class="info time">different value</span>
                    </div>
                </li>
            </ul>
        </div>
    </div>
    <div class="timeLineItemContainer">
        <div class="subItemMiddleContainer">
            <div class="timeLineHeader">
                <div>
                    <span>A TITLE</span>
                </div>
                <div>
                    <div>Some other text text</div>
                </div>
            </div>
        </div>
        <div class="subItemBottomContainer">
            <ul>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="info">Thu 12 March</span>
                    </div>
                </li>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">some additional text</span>
                        <span class="info time strikethrough">bla</span>
                        <div class="info time attention">
                            <span>yup</span>
                        </div>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">Text</span>
                        <span class="info">content</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">title</span>
                        <span class="info">value</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">Another title</span>
                        <span class="info">another value</span>
                    </div>
                </li>
                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">always visible</span>
                        <span class="info time strikethrough">just because</span>
                        <div class="info attention">
                            <span>attention!</span>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
    </div>
    <div class="timeLineItemContainer">
        <div class="subItemMiddleContainer">
            <div class="timeLineLeft">
                <div class="timeLinePipe"></div>
            </div>
            <div class="timeLineHeader">
                <div>
                    <span>Some other text</span>
                </div>
                <div>
                    <div>Ola!</div>
                </div>
            </div>
        </div>
        <div class="subItemBottomContainer">
            <ul>

                <li class="static">
                    <div class="timeLineRight timeLineInfo">
                        <span class="info">A date</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">label</span>
                        <span class="info">value</span>
                    </div>
                </li>
                <li class="toggable closed">
                    <div class="timeLineRight timeLineInfo">
                        <span class="label">anotehr label</span>
                        <span class="info time">different value</span>
                    </div>
                </li>
            </ul>
        </div>
    </div>

Javascript

代码语言:javascript
复制
var sw = screen.width;
var thresholdPercentageSwipeTimeLineItem = 15;
var thresholdPercentageSwipeDetailScreen = 10;    

$(".timeLineItemContainer").draggable({
    scroll: false,
    axis: "x",
    drag: function (event, ui) {
        if (ui.position.left < 0) {
            ui.position.left = 0;
        }
        else {
          if (calculateOffsetPercentage(ui.position.left) > thresholdPercentageSwipeTimeLineItem) {
              return false;
          };
        }
    },
    stop: function (event, ui) {
        $(this).animate({
           left: 0,
        }, {
           duration: 200,
           queue: false
        });
    }
}).click(function () {
    var nextObjs = $(this).toggleClass("visible").find(".toggable");

    $.each(nextObjs, function () {
        $(this).stop().animate({
            height: "toggle",
            queue: false
        }).toggleClass("closed");
    });

});

function calculateOffsetPercentage(screenValue) {
    return (100 / (sw / screenValue));
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-25 15:53:17

钉住了!

乍一看,$(".timeLineItemContainer").draggable({ ... });似乎正在消耗所有的事件,但实际上是jquery-ui-touch-punch.js在阻止一切。

jquery-ui-touch-punch.js的工作方式是防止所有触摸事件的结果执行默认行为。因此,我对jquery-ui-touch-punch.js做了一些调整,以获得正确的行为。

  1. 我将event.preventDefault()simulateMouseEvent()函数中删除。
  2. 我在mouseProto._touchStart事件中存储触摸的开始 tsx = event.originalEvent.touches[0].clientX; tsy = event.originalEvent.touches[0].clientY;
  3. 我在mouseProto._touchMove事件中添加了一个条件,以检查我是在水平方向还是垂直方向滚动。在水平方向的情况下,我正在执行event.preventDefault()。要做到这一点,您可以使用: // Higher then 1 means a (more) horizontal direction // Lower then 1 means a (more) vertical direction // 1 is an exact 45 degrees swipe, which will be handled as a vertical swipe if ((Math.abs(CurrentX - StartX)) / Math.abs(CurrentY - StartY) > 1) { event.preventDefault(); }

mouseProto._touchStartmouseProto._touchMove函数的最终结果如下:

代码语言:javascript
复制
var tsx = 0, 
    tsy = 0, 
    currentx = 0, 
    currenty = 0;

mouseProto._touchStart = function (event) {
    var self = this;

    tsx = event.originalEvent.touches[0].clientX;
    tsy = event.originalEvent.touches[0].clientY;

    // Ignore the event if another widget is already being handled
    if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
        return;
    }

    // Set the flag to prevent other widgets from inheriting the touch event
    touchHandled = true;

    // Track movement to determine if interaction was a click
    self._touchMoved = false;

    //// Simulate the mouseover event
    simulateMouseEvent(event, 'mouseover');

    //// Simulate the mousemove event
    simulateMouseEvent(event, 'mousemove');

    // Simulate the mousedown event
    simulateMouseEvent(event, 'mousedown');

};

mouseProto._touchMove = function (event) {
    // Ignore event if not handled
    if (!touchHandled) {
        return;
    }

    // Higher then 1 means a (more) horizontal direction
    // Lower then 1 means a (more) vertical direction
    // 1 is an exact 45 degrees swipe, which will be handled as a vertical swipe
    if ((Math.abs(event.originalEvent.changedTouches[0].clientX - tsx)) / Math.abs(event.originalEvent.changedTouches[0].clientY - tsy) > 1) {
        event.preventDefault();
    }

    // Interaction was not a click
    this._touchMoved = true;

    // Simulate the mousemove event
    simulateMouseEvent(event, 'mousemove');
};
票数 0
EN

Stack Overflow用户

发布于 2016-10-25 18:59:35

我尝试了OPs解决方案,但我认为jQuery UI draggable可能已经改变了,因为您上次写了这篇文章。在我的测试中,即使在完全删除jquery-ui-touch-punch.js之后,我仍然发现jQuery UI draggable仍在使用拖动事件。我不想深入研究jQuery的UI代码并对库进行分叉,所以我设计了一个相当简单的替代方案。

在我的场景中,我有一个收件箱列表,您可以将其项拖到左侧或右侧,以公开操作按钮。整个收件箱项目必须是可拖动的--因此使用拖动句柄不是一个选项。

如果触摸是在draggable元素中启动的,jQuery的draggable防止在触摸屏上垂直滚动。因此,如果屏幕上充满了可拖放的收件箱项目,那么用户就会陷入困境--无法向上或向下滚动。

对我起作用的解决方案是测量光标垂直位置的任何变化,并使用window.scrollBy手动滚动窗口的数量相同:

代码语言:javascript
复制
var firstY = null;      
var lastY = null;
var currentY = null;
var vertScroll = false;
var initAdjustment = 0;

// record the initial position of the cursor on start of the touch
jqDraggableItem.on("touchstart", function(event) {
    lastY = currentY = firstY = event.originalEvent.touches[0].pageY;
});

// fires whenever the cursor moves
jqDraggableItem.on("touchmove", function(event) {
    currentY = event.originalEvent.touches[0].pageY;
    var adjustment = lastY-currentY;

    // Mimic native vertical scrolling where scrolling only starts after the
    // cursor has moved up or down from its original position by ~30 pixels.
    if (vertScroll == false && Math.abs(currentY-firstY) > 30) {
        vertScroll = true;
        initAdjustment = currentY-firstY;
    }

    // only apply the adjustment if the user has met the threshold for vertical scrolling
    if (vertScroll == true) {
        window.scrollBy(0,adjustment + initAdjustment);
        lastY = currentY + adjustment;
    }

});

// when the user lifts their finger, they will again need to meet the 
// threshold before vertical scrolling starts.
jqDraggableItem.on("touchend", function(event) {
    vertScroll = false;
});

这将非常类似于触摸设备上的本机滚动。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31024233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档