Retrieve the direction of panning when the panning stops with hammer.js and limit the possible

I have integrated the hammer.js library along with its jQuery plugin. I followed the documentation and used the following code to initialize it on .game-card-mobile divs:

/* Creating a Hammer object for swipeable game cards */
var $gameCard = $('.game-card-mobile');
var $gameCardTouch = $gameCard.hammer();

$gameCardTouch.on("panright press panleft", function(ev) {
    console.log(ev.type);
}); 

This setup allows me to limit available actions to swiping and pressing on the element, however, when performing an action like panright, multiple entries are printed in the console even though only one swipe was made. To address this, I modified the initialization as shown below:

$gameCardTouch.on("panend", function(ev) {
    console.log(ev.type);
});

Now, it listens for the panend event which occurs at the end of the action, resulting in just one printout in the console. However, it always shows panend now, eliminating the restriction to specific actions and making it harder to identify the exact action performed.

Is there a way to combine these approaches so that I can get a single output of panright if the user swipes right, panleft if they swipe left, and the press event all captured once when the action is completed?

Answer №1

To achieve the desired outcome, consider utilizing a blend of the panright,press, and panleft actions along with the panend.

(function(){
    var direction;
    var $gameCard = $('.game-card-mobile');
    var $gameCardTouch = $gameCard.hammer();

    $gameCardTouch.on("panright press panleft", function(ev) {
        //Define the direction based on user action
        direction = ev.type;
    }); 

    $gameCardTouch.on("panend", function(ev) {
        //Utilize the stored direction variable here
        //Indicate completion of pan gesture and identify the action taken

        console.log(direction);

        //Execute necessary code based on direction
        if(direction === "whatever") ...
    }); 


}());

Answer №2

Expanding on Jack's point, a simpler solution can be implemented...

The ev.eventObject function returns integer values, which can be further explored at this link.

For instance, when dealing with the ev.direction property:

  • No movement = 0
  • Left = 2
  • Right = 4
  • Up = 8
  • Down = 16
  • Horizontal = 6
  • Vertical = 24
  • All directions = 30

In a concise manner:

var mc = new Hammer(body);

mc.on("panend", function(ev) {

  if (ev.direction == INT) {
    // Perform an action
  }

});

In a more descriptive way:

var mc = new Hammer(body);

mc.on("panend", function(ev) {

  //console.log(ev.direction);

  // Execute this for left direction
  if (ev.direction == 2) {
    // Perform an action
  }

  // Execute this for right direction
  if (ev.direction == 4) {
    // Perform an action
  }
});

Answer №3

While I'm currently using my mobile device, here's some pseudo code that might work:

let eventHandlers =  {
    swipeRight: function(){},
    press: function(){},
    swipeLeft:function(){}
}

 $gameCardTouch.on("swipeRight press swipeLeft", function(ev) {
      if(ev.type === 'swipeRight') {
         eventHandlers.swipeRight();
      } else if((ev.type === 'swipeLeft'){
         eventHandlers.swipeRight();
      } else {
       eventHandlers.press();
      }

You could also check out a similar example on this website:

Answer №4

While tackling a similar issue using Backbone, jQuery, and Hammer, I managed to find a solution by implementing the following code (sharing only relevant snippets). Hopefully, this can be helpful for someone facing a similar problem.

var Slideshow = Backbone.View.extend( {

    events: {
        "pan .slideshow-slide" : "handlePan",
        "panstart .slideshow-slide" : "handlePanStart",
        "panend .slideshow-slide" : "handlePanEnd",
    },

    state: {
        panHistory: [],
    },

    handlePanStart: function( evt ) {
        // fetching the X coordinate of the pan
        var startX = this.getPanXFromEvent( evt );

        // if unable to retrieve the X coordinate, exit the function
        if ( !startX ) {
            this.logger.warn( "Pan Start: Unable to find x", evt );
            return;
        }

        this.logger.log( "Pan Start", evt );

        // setting the pan array with the initial X coordinate as its first element
        this.state.panHistory = [ startX ];
    },

    handlePan: function( evt ) {
        // storing the pan history in a variable
        var pans = this.state.panHistory,
        // extracting the X coordinate from the pan event
        lastX = this.getPanXFromEvent( evt );

        // tracking changes on the X axis during the pan to determine user direction
        if ( lastX ) {
            pans.push( lastX );
        }
    },

    handlePanEnd: function( evt ) {
        // determining the direction of the pan
        switch ( this.getDirectionFromPanEvent( evt ) ) {
            case Hammer.DIRECTION_LEFT:
                // moving to the next slide if panned left and within range
                if ( !this.isOutOfRange( this.state.current + 1 ) ) {
                    this.logger.log( "Pan End: Moving Left", evt );
                    this.gotoNextSlide();
                    return;
                }

            case Hammer.DIRECTION_RIGHT:
                // moving to the previous slide if panned right and within range
                if ( !this.isOutOfRange( this.state.current - 1 ) ) {
                    this.logger.log( "Pan End: Moving Right", evt );
                    this.gotoPrevSlide();
                    return;
                }

            // Snapping back to the current slide by default
            default:
                this.logger.log( "Pan End: Snapping Back", evt );
                this.gotoSlide( this.state.current );
        }
    },

    getPanXFromEvent: function( evt ) {
        return Utils.getValue( "originalEvent.gesture.center.x", evt );
    },

    getDirectionFromPanHistory: function( evt ) {
        // variables for start, end, and last pan X coordinates
        var i, start, last, end,
        // caching the pan history array
        pans = this.state.panHistory;

        // returning 0 if there are not enough data points to calculate delta
        if ( pans.length < 2 ) {
            return 0;
        }

        // getting the starting pan X
        start = pans[ 0 ];
        // setting last and end to the last pan X
        last = end = pans[ pans.length - 1 ];

        // checking for changes in pan X to determine direction
        for ( i = pans.length - 2; last === end && i >= 0; i-- ) {
            last = pans[ i ];
        }

        // determining direction based on X coordinates
        return end > last && end > start ? Hammer.DIRECTION_RIGHT
            : end < last && end < start ? Hammer.DIRECTION_LEFT
            : 0;
    },
} );

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtain the origin of the image using dots in Javascript

Sharing my experience with setting a background image using Javascript. Initially, I tried using two dots like this: .style.backgroundImage = "url('../images/image00.jpg')" However, it did not work as expected. So, I removed one dot: .style.ba ...

Excluding certain source files in Typescript's tsconfig is a common practice to

My attempt to configure Typescript to exclude specific files during compilation is not working as expected. Despite setting exclusions in my tsconfig.json file, the code from one of the excluded files (subClassA.ts) is still being included in the compiled ...

Component template using Knockout.js and RequireJS for HTML widgets

Trying to implement the widget example for knockout from here. Unfortunately, I am having issues loading the template from an external HTML file using requirejs. ko.components.register('like-or-dislike', { template: { require: &apos ...

Upon encountering an expression, the code anticipated either an assignment or a function call, but instead found an expression, triggering the no

When using the forEach method within a function in JavaScript, I encountered a code compilation failure with the following error: Expected an assignment or function call and instead saw an expression no-unused-expressions. This error occurs for both ins ...

Identifying a Resizable Div that Preserves its Aspect Ratio During Resizing

Below is the HTML code snippet I'm working with: <div id="myid_templates_editor_text_1" class="myid_templates_editor_element myid_templates_editor_text ui-resizable ui-draggable" style="width: 126.79999999999998px; height: 110px; position: absolut ...

JavaScript heap ran out of memory near heap limit during mark-compacts, rendering the allocation ineffective, resulting in a failed Ionic 3 production build

While attempting to build a production version of my Ionic 3 app, I encountered the following error: "FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory". To troubleshoot this issue, I duplicated the en ...

Using an Angular route to trigger the resolution of data from a service

I'm having trouble figuring out how to implement Angular route resolve. The documentation does not provide much help for more complex aspects of the javascript framework like this. Here is the service I am using: app.service("AuthService", ["$http", ...

What is the best way in jQuery to show each element of an array one at a time with a space in an input field?

I have a large array filled with strings that I want to display one by one in a text field, automatically concatenated with a space bar. Below is my code: <script> x = 0; function abc() { for (i = 0; i < words[x].length; i++) { ...

What is the process for obtaining a compilation of warnings from the next.js terminal?

While running my project on VScode, I noticed a series of warnings appearing in the terminal. One specific warning that caught my attention is: The `bg-variant` mixin has been deprecated as of v4.4.0. It will be removed entirely in v5. on line 8 ...

Make an axios request multiple times equal to the number of items in the previous response

In my project, I am using the axios library to convert addresses into their respective coordinates. First, I fetch a list of addresses from an API. Next, I take the RESPONSE object and use Google API to convert each address to coordinates. Finally, I wan ...

Issue: Assertion violation: The use of <Link> element is restricted to within a <Router>. Any solutions or suggestions?

In my React and Next Js application, I am utilizing react-router-dom for routing purposes. The dependencies listed in the package.json file are as follows: This is how my current package.json file looks: { "name": "MUSIC", "versio ...

Component built in ReactJS for file uploads to a server running on Spring MVC/Data-REST

For quite some time, I have been on the lookout for a ReactJS component that enables file uploading from a browser, with the ability to save it to the server where the ReactJS application is deployed. I've come across several components that facilita ...

Alert: Github Dependabot has flagged Babel as vulnerable to arbitrary code execution when compiling meticulously designed malicious code

My Github Repository's Security section is flagging this issue as Critical for both my Frontend and Backend code. I'm having trouble grasping the nature of this alert. Can someone explain what flaw it represents? After updating my dependencies, ...

Navigating a Frame and Clicking a Link with Puppeteer: A Step-by-Step Guide

I am facing an issue with clicking on an anchor link within a page that is supposed to open a new tab for exporting a PDF. The problem arises because this link is located inside a frame within a frameset structure as shown below: https://i.stack.imgur.com ...

Retrieving Dropdown Values based on Selection in Another Dropdown

On my website, there are two dropdown lists available: 1) One containing Book Names 2) The other containing Links to the Books. All data is stored in an XML file structured like this: <?xml version="1.0" encoding="UTF-8"?> <BookDetail> <boo ...

The route parameters seem to be malfunctioning when using the Google Maps Directions API

Currently, I am attempting to transfer the latitude and longitude of a location from one HTML file to another using the $routeParams feature. In the second HTML file, I utilized the Google Maps directions API to display the directions from the source lati ...

Tips for designing a multi-level dropdown navbar

I am currently facing an issue with designing a navbar. I am aiming for Multi-Level Dropdowns, but whenever I click on More Services, it automatically closes the main dropdown menu. I have experimented with various approaches, but none of them seem to be ...

Having trouble detecting the Selection event of a Dropdown List upon loading

When a user chooses an option from the dropdown menu, I need to capture the selected item and perform an action: $("#user-list").on("change", function() { var selectedUser = $(this).find(":selected").text(); // Perform action with the selected us ...

Having trouble integrating Socket.io with Express.js?

I'm currently attempting to connect socket.io with express.js: var socket = require('./socket_chat/socket.js'); var express = require('express'), app = module.exports.app = express(); var io = require('socket.io&apo ...

The jQuery onClick function functions effectively for the initial two clicks; however, it ceases to

I am currently experimenting with jQuery to dynamically load a specific div from another page on my server into a designated section on the existing page. While the code is successfully functioning for the first two clicks on the website, it fails to work ...