【问题标题】:Edge Swipe Navigation边缘滑动导航
【发布时间】:2018-03-09 17:42:52
【问题描述】:

您能否推荐一个在使用基本 HTML 和 CSS 时实际上提供边缘滑动功能的 JS 库?

我已经搜索了所有内容,但没有找到该问题的真实来源。 我见过很多支持滑动手势但不支持边缘滑动的库。

我的最后一次尝试是使用 Hammer.js,我尝试将其实现为:

var swipe = new Hammer(document);
// detect swipe and call to a function
swipe.on('swiperight swipeleft', function (e) {
    e.preventDefault();
    var endPoint = e.pointers[0].pageX;
    var distance = e.distance;
    var origin = endPoint - distance;

    //swipe right to open nav
    if (origin <= 15 && e.type == 'swiperight') {
        // open main menu
        $('#navigation-menu').animate({
            left: '0'
        });
    } else {
        // close/hide menu(s)
        $('#navigation-menu').animate({
            left: '-100%'
        });
    }
});

此外,如果不使用任何库,如何使用 vanilla JS 实现移动边缘滑动以显示和隐藏内容(在我的情况下是导航菜单)? p>

此时我对任一解决方案/方向都持开放态度。

【问题讨论】:

  • 一个非常简单和愚蠢的方法是在页面顶部创建一个虚拟层。假设您的宽度为 400 像素,在 75 像素的左侧和右侧创建一个虚拟层,并将hammer.js 附加到该元素。您将立即获得边缘滑动。这不是一个很好的解决方案。但会帮助你实现你想要的。让我看看hammerjs
  • 您介意用小提琴示例发布答案吗?
  • 对图书馆的请求是题外话。
  • 此外,我正在请求/寻求解决方案。
  • 在这种情况下,您的问题应该反映这一点,并说明您到目前为止所做的尝试。

标签: javascript jquery hammer.js


【解决方案1】:

这里有一个解决方案,可以设置thresholdStart、End、Milliseconds。您可能需要整理代码,并将其移植到触摸事件中(我使用鼠标事件在浏览器中进行测试更容易)。

使用: swipeEdgeFromLeft 函数和 swipeEdgeFromRight 函数。

var div = document.body;
var mouse = {
  isDown: false,
  inLeft: false,
  inRight: false,
  downTimestamp: null
};
var width, thresholdStart, thresholdEnd, thresholdMilliseconds;

function resize(){
  width = window.innerWidth;
  thresholdStart = 0.1*width;//within 10% of screen width
  thresholdEnd = 0.13*width;//beyond 13% of screen width
  thresholdMilliseconds = 500;//must be done in 500 milliseconds
}
document.addEventListener("resize", resize, false);
resize();//initialize

div.addEventListener('mousedown'/*'touchstart'*/, function(e){
 var x = e./*touches[0].*/pageX;
 mouse.isDown = true;
 mouse.downTimestamp = performance.now();

 if(x < thresholdStart){
  mouse.inLeft = true;
 } else if(x > width-thresholdStart){
  mouse.inRight = true;
 }
});
div.addEventListener('mousemove'/*'touchmove'*/, function(e){
 
  var x = e./*touches[0].*/pageX;
  if(mouse.inLeft && x > thresholdEnd){
    mouse.inLeft = false;
    if(performance.now() - mouse.downTimestamp < thresholdMilliseconds){
      swipeEdgeFromLeft();
    }
  } else if(mouse.inRight && x < width-thresholdEnd){
    mouse.inRight = false;
    if(performance.now() - mouse.downTimestamp < thresholdMilliseconds){
      swipeEdgeFromRight();
    }
  }
});
div.addEventListener('mouseup'/*'touchend'*/, function(e){
 //var x = e./*changedTouches[0].*/pageX;
 mouse.isDown = false;
 mouse.inLeft = false;
 mouse.inRight = false;
 mouse.downTimestamp = null;
});
function swipeEdgeFromLeft(){
 console.log("edge swipe from left");
}
function swipeEdgeFromRight(){
 console.log("edge swipe from right");
}
body {
  max-width: 100vw;
  height: 100vh;
}
.bar {
  height: 100vh;
  background-color: rgba(0,0,0,0.4);
  position: fixed;
  pointer-events: none;
}
#left-inner-threshold {
  width: calc(0.1 * 100vw);
  left: 0;
}
#right-inner-threshold {
  width: calc(0.1 * 100vw);
  right: 0;
}
#left-outer-threshold {
  width: calc(0.13 * 100vw);
  left: 0;
}
#right-outer-threshold {
  width: calc(0.13 * 100vw);
  right: 0;
}
<div id="left-inner-threshold" class="bar"></div>
<div id="left-outer-threshold" class="bar"></div>
<div id="right-inner-threshold" class="bar"></div>
<div id="right-outer-threshold" class="bar"></div>

【讨论】:

  • 谢谢乔治!我将通过它并尝试将其转换为我的用例。
  • 调整大小的实现会和你写的一样吗?
  • 是的,我刚刚实现了调整大小。 thresholdStart 是用户可以开始滑动操作的屏幕左侧或右侧的像素数。例如 0.25*width 将是宽度的 25%。 thresholdEnd 类似,但它是触发滑动功能的点,如果它们在 thresholdStart 内开始并超出 thresholdEnd。
  • 非常感谢,这很有道理。抱歉,我只是在你之前编辑我的评论......
【解决方案2】:

这是使用 Hammer.js v2.0.8 对现有代码的解决方案

关于如何实现边缘滑动的解释可以找到@jovinbm 回答的here

$(document).ready(function () {

    const swipe = new Hammer(document);
    function getStartPosition(e) {
        const delta_x = e.deltaX;
        const delta_y = e.deltaY;
        const final_x = e.srcEvent.pageX || e.srcEvent.screenX || 0;
        const final_y = e.srcEvent.pageY || e.srcEvent.screenY || 0;

        return {
            x: final_x - delta_x,
            y: final_y - delta_y
        }
    };

    swipe.on('swiperight swipeleft', function (e) {
        e.preventDefault();
        const { x } = getStartPosition(e);
        console.log(x);
        //swipe right to open nav /* note the condition here */
        if (e.type == 'swiperight' && x >= 0 && x <= 50) {
            // open menu
            $('#navigation').animate({
                left: '0'
            });
            //swiping left should slide out nav and/or sub-nav
        } else {
            // close/hide menu
            $('#navigation, #task-menu').animate({
                left: '-100%'
            });
        }
    });
});

这是一个pen 展示它的实际操作:

【讨论】:

  • 非常感谢您提供此解决方案!我选择了 George Campbell 的答案,但你们两个都让我摆脱了这个兔子洞。
  • const final_x = e.center.x || e.srcEvent.pageX || e.srcEvent.screenX || 0;
【解决方案3】:

对于滑动,只有最终的pointerup 事件作为srcEvent 包含在传递给您的处理程序的事件对象中(请参阅http://hammerjs.github.io/api/)。初始的pointerdown 事件没有在锤子事件对象中提供,该事件带有滑动事件开始的初始位置的详细信息。幸运的是,您可以使用事件对象中的srcEvent 来获取事件初始pointerdown 事件的起始位置。

const getStartPosition = (e) => {
  const delta_x = e.deltaX;
  const delta_y = e.deltaY;
  const final_x = e.srcEvent.pageX || e.srcEvent.screenX || 0;
  const final_y = e.srcEvent.pageY || e.srcEvent.screenY || 0;

  return {
    x: final_x - delta_x,
    y: final_y - delta_y
  };
};

const handleSwipe = (e) => {
  const {x} = getStartPosition(e);

  if (x >= 0 && x <= 50) {
    // handle swipe from left edge e.t.c
  }
  else {
    // handle other case
  }
};

srcEvent 只是一个普通的 javascript 事件,它从 UIEvent 继承属性,因此是上面的 pageX/pageY api。这可能不适用于其他浏览器,因为其中一些是not standardized

【讨论】:

    猜你喜欢
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 2011-04-23
    • 1970-01-01
    相关资源
    最近更新 更多