Struggling to get image properly aligned using touch gestures

Currently, I am struggling with the task of centering my image based on the touch input that will drag it. For example, if the user touches the top right corner of the image, I want the image to automatically move so that its center aligns with that touch point.

The code snippet I have tried to achieve this is as follows:

img.style.left = e.touches[0].clientX + "px";
img.style.top = e.touches[0].clientX - shiftX + "px";

Unfortunately, the above code is not working as expected.

Below is the complete code for the touch start event:

img.addEventListener('touchstart', function(e) {
          beingDragged = img;
          start = e.target.parentNode.id;
          img.style.zIndex = 1;
          shiftX = e.touches[0].clientX - (img.width/2);
          shiftY = e.touches[0].clientY - (img.height/2); //code for dragging the image in the later touchmove event
          img.style.left = e.touches[0].clientX + "px";
          img.style.top = e.touches[0].clientY + "px";
        });

I have attempted to address this issue by using the shift values in the touchmove event as well as the bounding client rectangle, but none of these solutions have worked.

The touch move function itself works correctly, but I am focused on fixing this minor issue with the touchstart event.

Below is the CSS for the image:

img {
  position: absolute;
  width: 90%;
  height: 90%;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

In response to feedback, I tried to replicate and solve this error on a smaller scale, but when implementing the solution in the main code, the image gets flung off the screen.

Answer №1

Below are two possible solutions you can implement:

  1. When you grab the image, it stays attached to the cursor without centering on the click or move.
  2. When you click/move the image, it centers on the screen as mentioned in your response.

It is advisable to test the code without the presence of iframe HTML elements as they may not always provide accurate viewport information.

You can access the code and test it using the following links:

By utilizing the img.onload function, we ensure that the touch event listeners are only added post the full loading of the image in the DOM, offering precise calculations for its dimensions and position.

  • let rect = img.getBoundingClientRect()
    retrieves the position and size of the image on the screen. getBoundingClientRect() results in an object with properties like top, left, right, bottom, width, and height (indicating the size of the overall rectangle in pixels).
  • offsetX = e.touches[0].clientX - rect.left;
    and
    offsetY = e.touches[0].clientY - rect.top;
    are used to calculate the horizontal (offsetX) and vertical (offsetY) distances from the initial touch point to the top-left corner of the image (ensuring the touch point's position is maintained while dragging).
  • img.style.left = e.touches[0].clientX - offsetX + "px";
    and
    img.style.top = e.touches[0].clientY - offsetY + "px";
    will update the image's position on the screen as it is dragged/moved (setting top and left based on the current touch position minus the initially calculated offsets of the image).
// Explanation of the calculation
// rect.left and rect.top provide X and Y coordinates of the top-left corner of the image relative to the viewport.
// e.touches[0].clientX - position of the cursor relative to the page
// offset calculation determines the difference between the initial touch point and the top-left corner of the image's bounding box

Understand the difference between screenX/Y, clientX/Y, and pageX/Y here

<!DOCTYPE html>
<html lang="en">

<head>
  <meta name="viewport" content="width=device-width, user-scalable=no" />
  <meta charset="UTF-8" />
</head>

<body>
  <script>
    // Initial variable declarations
    let offsetX = null;
    let offsetY = null;
    let img = document.createElement("img");

    // Ensure the image is fully loaded before adding event listeners
    img.onload = function() {
      // Image dragging and repositioning
      img.onload = function() {
        img.addEventListener("touchstart", function(e) {
          e.preventDefault();
          let rect = img.getBoundingClientRect();
          img.offsetX = rect.width / 2;
          img.offsetY = rect.height / 2;
          offsetX = img.offsetX;
          offsetY = img.offsetY;
          img.style.zIndex = 1;
        });

        // Dragging from the clicked position:
        // img.onload = function () {
        //   img.addEventListener("touchstart", function (e) {
        //     e.preventDefault();
        //     let rect = img.getBoundingClientRect();
        //     offsetX = e.touches[0].clientX - rect.left;
        //     offsetY = e.touches[0].clientY - rect.top;
        //     img.style.zIndex = 1;
        //   });

        img.addEventListener("touchmove", function(e) {
          e.preventDefault();
          img.style.left = e.touches[0].clientX - offsetX + "px";
          img.style.top = e.touches[0].clientY - offsetY + "px";
        });
      };

      img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Location_dot_blue.svg/1200px-Location_dot_blue.svg.png";
      img.style.position = "absolute";
      img.style.height = "99.016px";
      document.body.appendChild(img);
  </script>
  </body>
  </html>

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

Experimenting with React components that showcase various components in a loop

Currently, I am working on a react-native app where I have a simple component that receives an array and displays it as markers on a map using react-native-maps. My goal is to write tests for this component. The test should verify that there is a marker p ...

Issues with managing ajax response handlers

Just dipping my toes into the world of ajax and attempting to create a reusable ajax request function. According to Firebug, the request is successfully fetching the correct data from my php file. However, for some reason, the response isn't getting i ...

Using Vue JS to apply a filter to data fetched from an API

Within my code, I attempted to retrieve users with the role of Admin and only their usernames from the API JSON data. However, I encountered an issue where it did not work as expected. "response": [ { "profil ...

Updating AngularJS to have the same page TITLE tag as the page's H1 tag

Is there a way to dynamically update the title tag of my page based on the H1 tag in AngularJS? In jQuery, I could achieve this by: var title = $('#content').find('h1').first().text(); if (title.length >= 1) { document.title = ...

Tips for arranging div elements in a grid-like matrix layout

I am facing a challenge in arranging multiple rectangular divs into a grid structure with 10 columns and 10 rows. The CSS styles for the top, bottom, left, or right positions must be in percentages to accommodate zoom in and out functionality without overl ...

Assigning a unique identifier to a button that will vary depending on the selected radio input

UPDATED HTML: The circumstances have changed because I am no longer in my office, but the concept remains unchanged. The situation is that on a certain part of a website, users have the option to choose from multiple saved addresses. Each address has a un ...

Keystroke to activate Ant Design Select and start searching

I'm currently using the 'react-hotkeys-hook' library and have successfully implemented a hotkey that logs in the console when triggered (via onFocus()). My goal now is to use a hotkey that will open a Select component and add the cursor to i ...

What factors influence the timing of Chrome's spell-check feature for a particular word?

Currently, I am troubleshooting a bug in our code that is related to text input behavior. The issue at hand is that in one field, when you start typing on Chrome, the word does not get red underlined until you press space. However, in another field, Chrom ...

Issues with scrolling divs not properly reaching the bottom of the content

I am facing an issue with 2 scrolling divs (outlined in red) that refuse to scroll to the bottom. I cannot seem to pinpoint what needs to be adjusted to resolve this problem. The thick outlined box represents a simulated browser window. View the code her ...

Ensuring maximum length validation on input

I am having an issue with the function "checkNumbers()". I am attempting to validate if my input does not exceed 10 numbers; while "isAllowedSymbol()" is functioning correctly, the other one is not. What could be causing this problem? function isAllowe ...

What method can I use in Javascript to extract the mealtype data from the Edamam nutritional API?

My goal is to extract the mealtype information from the API linked below. After reviewing the API, it seems that a POST request is required to retrieve mealType data. However, I am uncertain about the correct syntax for this request. For instance, if a u ...

Why is it that a label tag cannot be placed directly above an input tag?

On this particular page: http://getbootstrap.com/components/#input-groups-buttons If you modify the Go! button to a label (using Chrome inspector), you will observe that the Go! button is no longer positioned on top of the input field: https://i.sstatic ...

Can you suggest a simpler approach to implementing this function?

Greetings to all who are perusing this message. I have devised a technique for retrieving today's date along with the current time. If the deadline value in the database is null, it will fetch the current datetime and format it correctly. Otherwise, ...

Steps to open specifically the WhatsApp application upon clicking a hyperlink, image, or button

I need a code for my HTML website that will open the WhatsApp application when a user clicks on a link, image, or button while viewing the site on a mobile device. Only the WhatsApp application should be opened when a user interacts with a link on my webs ...

Is it possible to resize the background-image style?

When using the regular img tag in HTML, you can specify the width and height, and the browser will scale the image. If the dimensions are not too different from the original, the result is usually decent. For example, you can scale the avatar image to 32x ...

"Mastering the art of text animation: A beginner's guide

If you want to see a cool moving text animation, simply head over to this link: . The text will automatically type out and then clear just like the example below: https://i.sstatic.net/dAZW6.png Ever wondered how to create this kind of text animation? A ...

What is the best way to retrieve user input from a form within an Ajax.ActionLink?

My webpage is designed to be simple, featuring a picture and a comment section that functions as a partial view. I am looking to only refresh the partial view when a new comment is submitted. Here's what I have coded: <tr> & ...

Is there a specific method to access a JSON file with (js/node.js)?

Searching for a way to access user information stored in a JSON file using the fs module in node.js. Specifically looking to read only one user at a time. app.get("/1", function(req, res) { fs.readFile("users.json",function(data, err){res.write(data)}} W ...

I'm encountering an error when trying to return a value using the question mark operator in Vue.js - can someone explain why

When I attempted to retrieve the value using the question mark operator instead of using return twice, I encountered an error stating "Cannot read property 'omitDescription' of undefined." buttonText() { return this.omitDescription ? 'プ ...

Initiate requests to external servers from a NodeJS backend

My NextJS application seamlessly collaborates with a NodeJS server to act as the front end of my innovative three-tier architecture. 'use client'; import FormControl from '@mui/material/FormControl'; import InputLabel from '@mui/m ...