Sped up object outpacing the mouse pointer

I'm currently developing a drag and drop minigame, but I've encountered an issue with the touch functionality. The draggable function (using only cursor) works flawlessly, however, when I tried to implement touch support for mobile and tablet users following this tutorial: , I faced a major problem.

The dragged item seems to move faster than the cursor the further away it goes from the initial drag point.

You can witness the issue in action by checking out the JavaScript here: http://jsfiddle.net/0n8x6gue/1/

var container = document.querySelector("#section");
var activeItem = null;

var active = false;

container.addEventListener("touchstart", dragStart, false);
container.addEventListener("touchend", dragEnd, false);
container.addEventListener("touchmove", drag, false);

container.addEventListener("mousedown", dragStart, false);
container.addEventListener("mouseup", dragEnd, false);
container.addEventListener("mousemove", drag, false);

function dragStart(e) {

  if (e.target !== e.currentTarget) {
    active = true;

    // interacting item
    activeItem = e.target;

    if (activeItem !== null) {
      if (!activeItem.xOffset) {
        activeItem.xOffset = 0;
      }

      if (!activeItem.yOffset) {
        activeItem.yOffset = 0;
      }

      if (e.type === "touchstart") {
        activeItem.initialX = e.touches[0].clientX - activeItem.xOffset;
        activeItem.initialY = e.touches[0].clientY - activeItem.yOffset;
      } else {
        console.log("doing something!");
        activeItem.initialX = e.clientX - activeItem.xOffset;
        activeItem.initialY = e.clientY - activeItem.yOffset;
      }
    }
  }
}

function dragEnd(e) {
  if (activeItem !== null) {
    activeItem.initialX = activeItem.currentX;
    activeItem.initialY = activeItem.currentY;
  }

  active = false;
  activeItem = null;
}

function drag(e) {
  if (active) {
    e.preventDefault();
    if (e.type === "touchmove") {

      activeItem.currentX = e.touches[0].clientX - activeItem.initialX;
      activeItem.currentY = e.touches[0].clientY - activeItem.initialY;
    } else {
      activeItem.currentX = e.clientX - activeItem.initialX;
      activeItem.currentY = e.clientY - activeItem.initialY;
    }

    activeItem.xOffset = activeItem.currentX;
    activeItem.yOffset = activeItem.currentY;

    setTranslate(activeItem.currentX, activeItem.currentY, activeItem);
  }
}

function setTranslate(xPos, yPos, el) {
  el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
#bloc_page {
  width: 75%;
  margin: auto;
  min-width: 900px;
}

#section {
  display: flex;
  height: 500px;
  border: solid 1px;
}

h1 {
  text-align: center;
}


/* Game */

.yobi.ui-draggable-dragging {
  border: dashed rgba(53, 187, 243, 0.9);
}

#propositions {
  height: 100%;
  width: 25%;
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.yobi {
  border: solid rgba(53, 187, 243, 0.9);
  padding: 8px;
  margin: 10px;
  font-size: 24px;
  font-weight: bold;
  text-align: center;
  list-style-type: none;
  background-color: white;
  user-select: none;
}

 :hover {
  border-color: rgba(255, 134, 172, 0.9);
  cursor: pointer;
}

 :active {
  cursor: none;
}
<!DOCTYPE html>

<html lang="fr" xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta charset="utf-8" />
  <title>Test</title>
  <!--Title of the page in the browser tab-->
  <link href="main.css" rel="stylesheet" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script type="text/javascript" src="app.js" async></script>
  <script>
    (window.jQuery || document.write('<script src="/scripts/jquery-3.6.0.min.js"><\/script>'));
  </script>
  <!--Load jQuery from local file if CDN is not available-->
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
</head>

<body>
  <div id="bloc_page">
    <header>
      <h1>Days of the Week - 曜日</h1>
    </header>

    <section id="section">
      <div id="propositions">
        <ul>
          <li class="yobi">げつようび</li>
          <li class="yobi">かようび</li>
          <li class="yobi">すいようび</li>
          <li class="yobi">もくようび</li>
          <li class="yobi">きんようび</li>
          <li class="yobi">どようび</li>
          <li class="yobi">にちようび</li>
        </ul>
      </div>
    </section>
  </div>
</body>

</html>

Answer №1

It appears that the issue lies within the setTranslate function. Your block is already moving by adjusting the activeItem.currentX and activeItem.currentY variables before translating its position.

In this scenario, your block ends up moving at twice the speed of the cursor.

To resolve this problem, you can modify your drag function as follows:

function drag(e) {
    if (active) {
        e.preventDefault();
        
        if (e.type === "touchmove") {
            activeItem.currentX = e.touches[0].clientX - activeItem.initialX;
            activeItem.currentY = e.touches[0].clientY - activeItem.initialY;
        } else {
            activeItem.currentX = e.clientX - activeItem.initialX;
            activeItem.currentY = e.clientY - activeItem.initialY;
        }

        activeItem.xOffset = activeItem.currentX;
        activeItem.yOffset = activeItem.currentY;

        if (e.type === "touchmove") {
            setTranslate(activeItem.currentX, activeItem.currentY, activeItem);
        }
    }
}

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

Revalidating doesn't seem to work as expected in Next JS

Reviewing my code on the development server function Home(props) { console.log("Hello") return ( <ul> {props.user.map((user) => ( <li key={user.id}>{user.email}</li> ))} </ul> ) } expo ...

I am facing difficulties with deploying my Next.js App on Vercel. Whenever I try to deploy, I encounter an error stating that the Command "npm run build" exited with 1

Hey there! I'm currently following a tutorial by JavaScript Mastery on Next.js (big shoutout to you, sir). I've been trying to deploy it on Vercel, but running into some deployment issues and having trouble testing out different tutorials. Here&a ...

ESLint is parsing through alternative configurations

My .eslintrc file is very simple: { "extends": [ "twilio" ] } However, when I run eslint, I encounter this error message: The config "standard" was referenced from the config file in "/Users/MyAccount/Projects/my-sample-app/node_modules/cipher ...

Show another default value once an option has been chosen

I am looking to create a functionality where, after a user selects an option, the input will change to display "select another option" instead of showing the name of the selected option. For example: <select> <option value="" selected&g ...

Achieve a fading effect on an element as you scroll down the page

I successfully implemented a toggle audio button on my website, but now I would like it to fade in along with the scroll-to-top button that I also have (which operates similarly to the buttons on scrolltotop.com). Is there a simple way to achieve this? He ...

Is dirPagination failing to display pagination links correctly?

I am currently attempting to implement server-side pagination in my application, but I am facing challenges as the paging option seems to be missing. I have been following this tutorial for guidance. Below is a snippet of my code: JavaScript: $scope.vm= ...

Modifying the maximum value of a number field attribute in jQuery after a successful action

As I continue to learn jQuery, I encountered a situation with the following form: <form class="simple-checkout" enctype="multipart/form-data" method="POST" action="<?php echo admin_url('admin-ajax.php'); ?>"> <input type="hidd ...

React - Updating the document title upon user navigation away from the current page

I have encountered a challenge and I am seeking guidance on how to resolve it. Throughout our website, all pages have a default title based on our index.html file: <html lang="en"> <head> <title>My Page Title</title> ...

Guide to removing selected value from a combobox in Angular

I am working on a simple HTML file that consists of one combobox and one clear button. I want the clear button to remove the selected value from the combobox when clicked. Below is my code: mat-card-content fxLayout="row wrap" fxLayoutAlign="left" fxLayou ...

What is the best way to conditionally render table data in React JS using a loop?

Currently, I'm working on a project with React.js and facing challenges in iterating through a data array to selectively render elements based on each data node's properties. The dataset is structured as follows: var requests = [ {"id": ...

Setting up the InMemoryCache in Vue ApolloConfiguring the InMemoryCache

I've set up vue-apollo following the instructions in the apollo.config.js file from this guide: (I'm using VSCode). Now, I want to configure the InMemoryCache to exclude the typeName (addTypename: false) like it's explained here: https://w ...

The content has been successfully loaded using ajax, but it is not displaying

I've been experimenting with djax and have noticed that when I click on an anchor tag, the URL changes as expected. However, even though the page source reflects this change, the contents of the page itself remain unchanged. Any thoughts on why this m ...

Ways to transfer a v-model from the parent component to a template

I'm currently in the process of designing the user interface for a search page and I want to utilize components to help with code reusability. However, I am facing a challenge in figuring out how to pass the model of the page to the search component. ...

sending a parameter in the reverse url using JavaScript

coding in javascript let address = '{% url candidate_resume "cnd_id" %}'; address = address.replace("cnd_id",id); document.getElementById('cell2').innerHTML= '<a href="' + address + '"> View Resume < ...

Contrast: Colon vs. Not Equal Sign (Typescript)

Introduction Hello everyone, I am new to Typescript and currently grappling with some fundamental concepts. When defining a parameter for a function, I typically specify the type like this: function example(test: string){...} However, as I delve deeper ...

Do I need to utilize getStaticProps along with JSON imports in Next.js?

Is it necessary to use getStaticProps in order to render static data from a JSON or typescript file, or can the data be imported without using getStaticProps? The documentation I read didn't provide a clear answer. projects.tsx const projects: [ { ...

Having difficulty implementing a personalized color scheme for the mui component

Attempting to set the background color as midnightBlue but encountering an error: Error: Cannot read properties of undefined (reading '100') Upon reviewing the syntax, no errors were found. Perhaps this issue stems from a dependency problem? ...

The latest URL is not launching in a separate tab

Looking for some assistance with this code snippet: <b-btn variant="primary" class="btn-sm" :disabled="updatePending || !row.enabled" @click="changeState(row, row.dt ? 'activate' : 'start&apo ...

Overriding the Ajax URL

During an AJAX request in a Rails app triggered by onchange event, I am encountering an issue with the URL being called. The function for the request is a simple PUT operation: function quantityChange(id, val) { $.ajax({ url: 'cart_items/ ...

Display debugging information in the console using bunyan

child.log.info('info'); child.log.debug('debug'); When running the command: node app.js | bunyan -o short -l debug I am encountering an issue where only INFO messages are displayed and DEBUG messages are not showing up. I want to be ...