Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edge Swipe Navigation

Can you recommend a JS library that actually provides edge swipe functionality when working with bare-bones HTML & CSS?

I've searched all over and haven't found a source of truth for that problem. I've seen lots and lots of libraries enabling swipe gestures but not edge swipe.

My last attempt was using Hammer.js which I've tried implementing as:

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%'
        });
    }
});

Further, if not using any library, how can I implement a mobile edge swipe to show and hide content, (in my case it'd be a navigation menu) with vanilla JS?

At this point I'm open to either solution/direction.

like image 224
Null isTrue Avatar asked Mar 09 '18 17:03

Null isTrue


2 Answers

Here is a solution, you can set thresholdStart, End, Milliseconds. You may want to tidy up the code, and port it for touch events (I used mouse events for testing in my browser more easily).

Use: swipeEdgeFromLeft function and swipeEdgeFromRight function.

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>
like image 72
George Avatar answered Oct 31 '22 12:10

George


Here's a solution to your existing code using Hammer.js v2.0.8

The explanation for how to achieve the edge swipe can be found here answered by @jovinbm.

$(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%'
            });
        }
    });
});

Here's a pen showing it in action:

like image 3
Jonca33 Avatar answered Oct 31 '22 13:10

Jonca33