Obtain Touch Event Coordinates Relative to Small Frame Buffer Element

I created a dynamic fluid simulation with shaders (utilizing THREE.js) for my website. In order to ensure quick performance even on mobile devices, I opted to simulate at a lower resolution (4 times smaller than the Render Target). While I successfully implemented it for Mouse Events, I have been struggling to accurately scale Touch Events to correspond with actual touch positions.

function handleMove(evt) {

        evt.preventDefault();
        var touches = evt.targetTouches;
        var x = 0, y = 0;

        if (BufferBUniforms.iMouse.value.z === 1) {

            var element = document.getElementById("container").getBoundingClientRect();
            var bodyRect = document.body.getBoundingClientRect();

            var h = (element.top - bodyRect.top);
            var w = (element.left - bodyRect.left);

            // One method I attempted.
            x = (touches[0].pageX - w) / scaleMax;
            y = height - (touches[0].pageY - h) / scaleMax;

            // Another approach I experimented with.
            x = (touches[0].pageX - w) / scaleMax;
            y = height - (touches[0].pageY - h) / scaleMaxO;

            BufferAUniforms.iMouse.value.x = x;
            BufferAUniforms.iMouse.value.y = y;

        }

    }

Below is a snippet showcasing the initialization of some of the variables referenced above:

scale = window.devicePixelRatio;
renderer.setPixelRatio(scale);
container.appendChild(renderer.domElement);

height = window.innerHeight * 0.25;
height = THREE.Math.floorPowerOfTwo( height )
scaleMax = window.innerHeight / height;
width = window.innerWidth * 0.25;
width = THREE.Math.floorPowerOfTwo(width)
scaleRatio = width / height;
scaleMaxO = window.innerWidth / width;
renderer.setSize(width * scaleMax, height * scaleMaxO);

While the functionality works when utilizing Chrome Dev Tools in Mobile Emulator, I encountered issues when testing on a Samsung S9 Plus device.

View the entire project here

Answer №1

If you are using a smaller render target to fill the canvas, the code should look like this:

const rect = renderer.domElement.getBoundingClientRect();
const x = (touches[0].clientX - rect.left) * renderTargetWidth / rect.width;
const y = (touches[0].clientY - rect.top ) * renderTargetHeight / rect.height;

The X and Y coordinates are now in pixels within the render target, but you may want to invert Y:

const y = renderTargetHeight - 
     (touches[0].clientY - rect.top) * renderTargetHeight / rect.height;

This code will also work for the mouse events:

function computeRenderTargetRelativePosition(e) {
  const rect = renderer.domElement.getBoundingClientRect();
  const x = (e.clientX - rect.left) * renderTargetWidth  / rect.width;
  const y = (e.clientY - rect.top ) * renderTargetHeight / rect.height;
  return {x, y};
}

renderer.domElement.addEventListener('mousemove', (e) => {
  const pos = computeRenderTargetRelativePosition(e);
  ... do something with pos...
});

renderer.domElement.addEventListener('touchmove', (e) => {
  const pos = computeRenderTargetRelativePosition(e.touches[0]);
  ... do something with pos...
});

If CSS transforms are applied, different code will be required. See below for an example:

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

Implement styling based on user input - Transmit form data via PHP to designated email address

My form allows people to provide their details and share their current timetable. I then group them based on suitable times The PHP form currently prints either 'work' or 'free' into a table cell, based on user selection in the form, a ...

Encountering an issue while trying to import the D3.js library into my React.js application

I'm having trouble with properly importing the d3.js libraries in my react.js app. I am using import * as d3 from 'd3' to import everything and store it in the d3 namespace, but I keep getting an error that says - Cannot read property ' ...

Has anyone else encountered the issue where the JavaScript for Bootstrap version 4.3.1 is malfunctioning on Firefox version 65.0.1?

While browsing through the bootstrap v 4.3.1 documentation on firefox v 65.0.1, I noticed an issue with the javascript not functioning properly. For instance, the carousel component is not progressing to the next slide with its transition animation as it s ...

What makes the creation of Javascript objects so flexible and dynamic?

Recently, I've been exploring the concept of creating new objects in JavaScript. It's interesting to note that in JS, every object creation is dynamic. This allows you to create an object and then add properties later on. Even fields created in t ...

When selecting a different file after initially choosing one, the Javascript file upload event will return e.target as null

Currently, I have implemented file uploading using <input>. However, when attempting to change the file after already selecting one, the website crashes and states that event.target is null. <Button label="Upload S3 File"> <input ...

Issues with displaying Datatables after using jquery show()

Attempting to display a hidden table, <div id="buglist" style="display: none" <?php include_once("partials/bugs.php");//this is where the datatables table is located </div upon executing $("#buglist").show(); The table appears, but i ...

A compilation of approved classes for the quill toolbar

The instructions provided in the documentation for the quill module indicate that you can manually create a toolbar using HTML, and then pass the corresponding DOM element or selector to Quill. This will result in the ql-toolbar class being added to the to ...

Experiencing an excessive amount of re-renders can lead to performance issues. React implements limits on the number of renders to avoid potential infinite

Would appreciate assistance in solving this code quandary. Whenever the "/" is removed before "about" and "id", it strangely does not generate any errors. import Navbar from "../components/Navbar"; import Footer from "../components/Footer& ...

Calculate the total sum of the properties of the objects within the array

I need to calculate the total sum of unit prices. Any suggestions on how I can achieve this? This is what the array looks like: $scope.items = [ { id: '1', name: 'Phone', quantity: '1', u ...

Issue with sizing and panning when using a combination of Three.js and CSS3Renderer

This issue is specific to Chrome. Here's what I have experimented with: I am utilizing the webGL renderer to position a plane geometry in a 3D environment using threejs. This particular code is running within a class, with the scene as one of its me ...

Assistance with Redirecting Responses in Next.js API Routes

I'm currently working on implementing a login functionality in Next.js. I have made significant progress but I am facing an issue with redirecting to the homepage after a successful login. My setup involves using Next.js with Sanity as the headless CM ...

Setting up Socket.io results in numerous transport polling GET requests being initiated

I have set up an express.js server-side and followed the socket.io guide. However, I am facing issues with the socket connection not being successful, and there seems to be a high number of unexpected GET requests like this: https://i.stack.imgur.com/GDGg ...

What is the process for incorporating custom controls into the Mantine Embla Carousel within a Next.js environment?

Check out this code snippet: import React from "react"; import { Container } from "@mantine/core"; import { Carousel } from "@mantine/carousel"; import { ArticleCard } from "@/components"; import { cards } from " ...

Issue - unable to access data-attribute of child element (undefined)

UPDATE: TYPO ALERT! I MISSED A MISTAKE. Please disregard this question. I am looking to grab the data-key attribute from the span inside an li-element when the checkbox is checked. <li class="result-set-list-item"> <input class="result-select ...

What is the best way to incorporate a JavaScript file into a webpage specifically for browsers that are using IE 7 or an earlier version?

Is there a way to dynamically include a Java Script file depending on a certain condition? For instance, I am looking for a solution to incorporate a JavaScript file that provides JSON support specifically when the user's browser is Internet Explorer ...

Looking for a smart way to extract all the selected elements from a form?

I am attempting to retrieve all the checked items from this form using JavaScript. I have looked at previous solutions, but none of them fit my requirements. <form id="checkform" class="container" style="margin-top:20px;"> <input type="checkb ...

Struggling to find a solution for your operating system issue?

We are currently attempting to utilize the markdown-yaml-metadata-parser package for our project. You can find more information about the package here. Within the package, it imports 'os' using the following syntax: const os = require('os ...

"Upon choosing a file using the HTML input file multiple element, a triggered event

After selecting multiple files using the input type="file" HTML element, I am eager to start uploading them. Can you tell me which event I should use to execute code immediately after finalizing my file selection? This is what my HTML code looks like: &l ...

``Is there a way to access the $attrs data of child DOM elements from within a controller?

Imagine having a controller and multiple children DOMs each with their unique data attributes. <!DOCTYPE html> <html ng-app="plunker"> <head> <meta charset="utf-8" /> <title>AngularJS Plunker</title> < ...

Is it possible to use JQuery to trigger a click event on text inside

Trying to implement a JQuery method that triggers when the code below is clicked: <div class="content_sub_list"> <img src="/imgs/close-icon.jpg" class="exit_sub_list"/> hello </div> The current JQuery code in use: $(document).r ...