The Raycaster feature malfunctions when the phone is tilted to landscape orientation

When I try to select objects on my PC, it works perfectly fine. However, when I attempt to run the same process on my phone, it doesn't seem to work!

PC screenshots: https://i.sstatic.net/S0goX.jpg Phone screenshots: https://i.sstatic.net/NzvrT.jpg

NOTE: On the phone, I rotated the canvas 90 degrees using CSS (I suspect this operation might be causing the issue, but I'm not entirely sure why):

transform-origin: left top;
transform: rotate(90deg);
import * as THREE from 'three';

export class PickupManager {

    raycaster: THREE.Raycaster;

    camera: THREE.Camera;

    scene: THREE.Scene;

    canvas: HTMLCanvasElement;

    constructor(camera: THREE.Camera, scene: THREE.Scene, canvas: HTMLCanvasElement) {

        this.raycaster = new THREE.Raycaster();

        this.camera = camera;

        this.scene = scene;

        this.canvas = canvas;

        this.addEventListener();
    }

    pickedObject: THREE.Object3D | any;

     ljj1: THREE.Object3D = null;
     ljj2: THREE.Object3D = null;
     ljj3: THREE.Object3D = null;
     ljj4: THREE.Object3D = null;
     ljj5: THREE.Object3D = null;

    pick = (normalizedPosition: THREE.Vector2) => {

        this.ljj1 = this.ljj1 || this.scene.getObjectByName("LJJ1");
        this.ljj2 = this.ljj2 || this.scene.getObjectByName("LJJ2");
        this.ljj3 = this.ljj3 || this.scene.getObjectByName("LJJ3");
        this.ljj4 = this.ljj4 || this.scene.getObjectByName("LJJ4");
        this.ljj5 = this.ljj5 || this.scene.getObjectByName("64mmB016");

        // Update the ray with camera and mouse position
        this.raycaster.setFromCamera(normalizedPosition, this.camera);

        // Calculate intersection of objects and ray
        const objects = [this.ljj1, this.ljj2, this.ljj3,this.ljj4, this.ljj5];
        const intersectedObjects = this.raycaster.intersectObjects(objects,true);

        if (intersectedObjects.length > 0) {    
            this.pickedObject = intersectedObjects[0];

            const obj:THREE.Object3D = this.pickedObject.object;
            // Output name of selected object
            console.log(obj.name );

        } else {

            console.log("Not found!")
        }
    }

    getCanvasRelativePosition = (event: MouseEvent | TouchEvent) => {

        const rect: DOMRect = this.canvas.getBoundingClientRect();

        const position: THREE.Vector2 = new THREE.Vector2();

        if (event instanceof MouseEvent) {

            position.x = event.clientX ;
            position.y = event.clientY;

        }

        else if (event instanceof TouchEvent) {

            const touch: Touch = event.changedTouches[0];

            position.x = touch.clientX - rect.left;
            position.y = touch.clientY - rect.top;

        }

        else {
            throw "Incorrect event, needs MouseEvent or TouchEvent";
        }

        return position;
    }

    getPickPoint = (event: MouseEvent | TouchEvent) => {

        const canvasPosition = this.getCanvasRelativePosition(event);

        const pickPoint:THREE.Vector2 = new THREE.Vector2();

        // Normalize mouse position to device coordinates. x and y values range (-1 to +1)
        pickPoint.x = (canvasPosition.x / window.innerWidth ) *  2 - 1;
        pickPoint.y = (canvasPosition.y / window.innerHeight) * -2 + 1;

        return pickPoint;

    }

    addEventListener = () => {

        this.canvas.addEventListener('mousedown', this.onMouseDown, false);

        this.canvas.addEventListener('touchstart', this.onTouchStart, false);

    }

    onMouseDown = (event: MouseEvent) => {

        event.preventDefault();

        this.pick(this.getPickPoint(event));

    }

    onTouchStart = (event: TouchEvent) => {

        event.preventDefault();

        this.pick(this.getPickPoint(event));

    }

}

I am trying to obtain the ljj1,ljj2,ljj3,ljj4,ljj5 objects. While I can successfully do so on a PC, I encounter difficulties when attempting on a phone.

Answer №1

If you have applied a CSS rotation to the canvas, it will affect how mouse/touch coordinates are calculated.

Dealing with CSS transformed elements requires writing more complex code.

To obtain mouse coordinates, you can utilize event.offsetX and event.offsetY

For touch coordinates, you will need to create synthetic events that relay the position back to the browser in order to generate event.offsetX and event.offsetY.

Check out How to get a canvas relative mouse position of a CSS 3D transformed canvas?

Take a look at this example and this gist as well

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

Tips for executing JavaScript code within a component

Looking to incorporate a parallax effect into an HTML element in my template. Have the code written, but uncertain of where to place it so that it runs each time the page is scrolled. let pos = document.body.scrollTop; document.getElementById('parall ...

The stroke width varies unpredictably for outliers within the react-boxplot component

I've been working with the react-boxplot module and I'm trying to customize my outliers to look like a ring as shown in this image Below is the code snippet I have been using: <Boxplot width={boxplotWidth} height={20} ...

Meteor: Form a fresh collection using a single attribute from a current collection

In my Meteor app, I have a collection fullList = new Mongo.Collection('fullList');. This collection consists of an array of objects with attributes like Color, Factor, and Tot. My goal is to create a new collection or array that specifically con ...

Is there a way to use HTML and JS to draw custom lines connecting elements?

Sorry if this question has been asked before. Is there a way to create straight lines connecting HTML elements with just HTML and JavaScript, without relying on SVG or Canvas? If so, what would be the most effective approach? ...

How to customize nouislider appearance using Bootstrap styles

I've been attempting to style the noUi tooltips to match the bootstrap design, but I've been unsuccessful so far. I'm wondering if there's an easy way to achieve this. I tried to structure the markup based on the bootstrap template ava ...

Using Foreach to reference data as "this"

I am attempting to iterate through this information in order to assign a value to each. const keys = Object.keys(response.data) keys.forEach((index, element) => { // let query = "this."+element this[element] = response.data[element] }); The de ...

The Ajax post is only activated on one occasion

Hello there, I am encountering a problem with an ajax function. My goal is to post data to a database and then update a table that displays the database information. Strangely, the process works fine the first time - data is posted and the table is refresh ...

Verify the functionality of JavaScript to ensure it is enabled and functioning properly

I have experimented with various methods to determine if JavaScript is enabled and running correctly. Typically, I would use a simple test like this: $('.jstest').html('JavaScript works.'); <p class='jstest'></p> ...

What is the reason why Discord.js is not utilizing the message object?

My goal was to send a series of buttons ahead of time for collection, but I encountered an issue when running the collector. The error message displayed: const collector = message.createMessageComponentCollector({ componentType: ComponentType.Button, ...

Two controller files causing conflict with ng-click functionality in partial view

Currently, I am developing a project using MVC4 with angular JS and implementing ng-include to incorporate a partial view within my main view. I have encountered an issue when attempting to click a button located in the partial view. In my setup, there ar ...

``Do not forget to close the modal window by clicking outside of it or

I am looking for a way to close the modal window either when a user clicks outside of it or presses the escape key on the keyboard. Despite searching through numerous posts on SO regarding this issue, I have been unable to find a solution that works with ...

jQuery - Reveal one div while concealing another

I've been working on a script to toggle between two divs onClick - opening one while closing the other if it's already open. I'm fairly new to jQuery and Javascript, having mainly worked with HTML/CSS. Script I found: http://jsfiddle.net/J ...

What is the best way to set a default selected option in an ng-multiselect-dropdown using Angular?

Here, I am retrieving data from the database and storing it in an events array. The data in this events array is displayed on the book-ticket.component.html using ng-multiselect-dropdown. Upon selecting an option, the corresponding data is stored in this.e ...

Manipulating events through adjusting values of a JQuery-UI range-slider

My range-slider's values are being set with the code: $('...').slider( 'values', [ 0, 10000 ] );. However, I am facing an issue where this line triggers the change( event, ui ) event twice. Is there a way to ensure it only triggers ...

It appears that when importing from a shared package in lerna, the name must include "src" at the end for Typescript or Javascript files

I am currently working on a straightforward lerna project structure as shown below: Project | +-- packages | | | +-- shared | | | | | +-- src | | | | | +-- index.ts | | +-- someDir | | | +-- usesShared | ...

having difficulty in transmitting json data using ajax

Struggling to send JSON data to my PHP script via AJAX and it keeps returning NULL as a response. The jQuery script I'm using involves creating a JSON data on a click event and then attempting to send it to the PHP script. Here's a snippet of the ...

Mastering Vue.js: Leveraging v-model within a v-for loop and implementing watchers

After retrieving a list of debits and credits from a server using the fetch function, I store them in my Vue application: const myApp = Vue.createApp({ data(){ return{ debits:[], credits:[], //cut } }, me ...

Can you tell me the proper term for the element that allows CSS properties to be changed after a link has been clicked?

I have integrated a horizontal scrolling date selector on my website, and it is functioning well. However, I am facing an issue while trying to change the CSS properties of a clicked date link using jQuery. Despite successfully firing the click event, I am ...

Is there a way to incorporate the req.setHeaders method with the res.redirect method in the same app.get function?

var express = require('express'); var app = express(); var PORT = process.env.PORT; app.get('/', function(req, res){ res.json('To search for images, enter your query parameters like this: https://api.cognitive.microsoft.com/bi ...

Troubleshoot: Inline Styling Problem with Bootstrap 4 Popover

Is there a way to dynamically change the color of the Bootstrap 4 popover title using inline HTML style attributes? It seems that the plugin is removing them without any logical reason. Below is an example demonstrating this issue: $('#test'). ...