Stop clicks from interfering with dragging in three.js

My GLTF model in Three.js has objects within it, and I want the camera to zoom in on an object when the user clicks on it. However, I am facing an issue where if the user drags after clicking on an object, a click is triggered upon releasing the mouse button, causing the camera to zoom in again. I tried using a "dragged" variable with nested if statements to solve this problem, but it's not working as expected. Can anyone suggest a solution?

var mesh=[];

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2()

function onClick(event) {
    event.preventDefault();

    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

    raycaster.setFromCamera( mouse, camera );

    var intersects = raycaster.intersectObjects( scene.children, true );

    var dragged = false
    window.addEventListener('mousedown', function () { dragged = false })
    window.addEventListener('mousemove', function () { dragged = true })
    window.addEventListener('mouseup', function() {
        if (dragged == true) { return }
        //Click Tree006 to focus
    if ( intersects.length > 0 && intersects[0].object.name==="Tree006") {
        var object = intersects[0].object;
        zoomInTimeline(mesh["Tree006"].position.x, mesh["Tree006"].position.y, mesh["Tree006"].position.z, 5);

    console.log( 'Intersection:', intersects[ 0 ] );
    }

    //Click anywhere outside of object to leave focus
    if ( intersects.length > 0 && intersects[0].object.name!=="Tree006") {
        var object = intersects[0].object;
        gsap.to( camera.position, {
            duration: 1, // seconds
            x: 6,
            y: 4,
            z: 4,
            onUpdate: function() {
                controls.enabled = true;
                // controls.enableRotate = true;
                
            }
        } );
    }

    //Click object to focus
    if ( intersects.length > 0 && intersects[0].object.name==="Tree001") {
        var object = intersects[0].object;
        zoomInTimeline(mesh["Tree001"].position.x, mesh["Tree001"].position.y, mesh["Tree001"].position.z, 5);
    
    console.log( 'Intersection:', intersects[ 0 ] );
    }

    //Click anywhere outside of object to leave focus
    if ( intersects.length > 0 && intersects[0].object.name!=="Tree001") {
        var object = intersects[0].object;
        gsap.to( camera.position, {
            duration: 1, // seconds
            x: 6,
            y: 4,
            z: 4,
            onUpdate: function() {
                controls.enabled = true;
                // controls.enableRotate = true;
                
            }
        } );
    }
})
}

Answer №1

To understand this process in a step-by-step manner:

  1. The user initiates a click by pressing down on the mouse.
  2. While keeping the mouse button pressed, the user moves the cursor.
  3. If the user releases the mouse without moving it, it is registered as a click; if they release it after moving, it becomes a drag action.
let isDragging = false;
let isMouseDown = false;

window.addEventListener('mousedown', function () {
    isMouseDown = true;
});
window.addEventListener('mousemove', function () {
    if(isMouseDown) {
        isDragging = true;
    }
});
window.addEventListener('mouseup', function() {
    // If not dragging, treat it as a click
    if(!isDragging) {
        // Perform all actions for a click event here
    }

    // Reset flags
    isMouseDown = false;
    isDragging = false;
});

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

Is there a way to utilize localStorage to retain a classlist toggle status for a light/dark mode theme switch on the browser?

I am currently working on a portfolio website that features a light/dark mode theme switch. The functionality of the switch is working properly, but it doesn't save the user's preference when they refresh the page or navigate to another section. ...

Utilize the $setValidity function within ng-repeat to validate input fields

I am facing an issue with my form that is being repeated in an ng-repeat. Below is a snippet of the form. I need to implement custom validation using $setValidity in the controller. However, I am struggling to access input names by index in the controlle ...

What is causing the issue with using transition(myComponent) in this React 18 application?

Recently, I have been immersed in developing a Single Page Application using the latest version of React 18 and integrating it with The Movie Database (TMDB) API. My current focus is on enhancing user experience by incorporating smooth transitions between ...

What could be causing the lack of data with 'react-hook-form'?

I have encountered an issue while working with react-native and using 'react-hook-forms' for creating dynamic forms. The problem is that the data object returned is empty, even though it should contain the values entered in the input fields. When ...

What is the reason objects cannot be compared in JavaScript?

I have a straightforward code snippet here. Its purpose is to authenticate the user against the author of the post and grant the authenticated user access to edit the post. exports.edit = function(req, res){ Post.findById(req.params.post_id, function ...

Managing empty props in React applications

I am facing an issue where I need to display an image fetched from an API on app start, but when I try to render it in React, the application crashes with the error message: TypeError: Cannot read property 'icon' of undefined. Although the icon ...

Is there a way to trigger a function from a specific div element and showcase the JSON data it retrieves in

I am working with a React JS code page that looks like this: import React, { useState } from "react"; import { Auth, API } from "aws-amplify"; function dailyFiles(props) { const [apiError502, setApiError502] = useState(false); // Extracted into a re ...

Customize React Hook Form version 7 by incorporating a unique input method for handling empty values

Introducing my custom Input component: export type InputProps = { error?: string } & InputHTMLAttributes<HTMLInputElement> export const Input: FunctionComponent<InputProps> = ({ error, ...props }) => ( <input {...props} /> ) ...

Verify whether a class or id is present in the HTML response obtained from an AJAX request

Is there a way to check the content of HTML returned by an AJAX call before rendering it to avoid any flickering effect? I am aware of using hasClass() to check for classes, but in this scenario, the AJAX response is returning HTML. I can append the HTML ...

Utilizing pixel values for Material-UI breakpoints rather than using the default sm, md, lg, xl options

Below is the code snippet that I am using: [theme.breakpoints.only('lg')]: {} The above code works perfectly and shifts at the desired breakpoint. However, when I implement the following: [theme.breakpoints.between('1200', '1021&a ...

In Ember.js, where should I place the initialization code for a controller? I attempted to set it up in the routes

With my experience working with ember.js and highcharts, I have come across some examples that were too simplistic for me to grasp how to set up the chart objects and render them properly. I have explored initializers and understand the significance of ro ...

Adding methods to a constructor's prototype in JavaScript without explicitly declaring them

In the book Crockford's JavaScript: The Good Parts, there is a code snippet that demonstrates how to enhance the Function prototype: Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; }; Crockford elabo ...

Launching PDF on IE11 in a new tab seamlessly without any prompts - mssaveoropenblob

We are in the process of transitioning an ASP.NET MVC application that used to have the functionality of opening a PDF file in a new tab using FileContentResult. return new FileContentResult(byteArray, "application/pdf"); As part of this migration to Rea ...

I'm having trouble getting the second controller to function properly in my AngularJS application

I've been looking everywhere for a solution on how to implement two controllers, but I can't seem to get it working. Could there be something wrong with my HTML or could the issue lie in my script? Here is the JavaScript code: <script> v ...

Is there a way to make changes to a pre-uploaded PDF document?

I'm looking to include a footer in a PDF file that is currently stored on the server. For instance, I have uploaded a file to uploads/aaa.pdf and now I need to insert a footer into the same file located at uploads/aaa.pdf Does anyone know how I can ...

Determine the number of rows in an Excel spreadsheet using JavaScript

Currently, I am working on a codeigniter project where I need to upload an Excel file. However, before uploading the file, I want to display the number of records it contains. To achieve this, I decided to create a function within my script and then call t ...

Step-by-step guide on clipping a path from an image and adjusting the brightness of the remaining unclipped area

Struggling to use clip-path to create a QR code scanner effect on an image. I've tried multiple approaches but can't seem to get it right. Here's what I'm aiming for: https://i.stack.imgur.com/UFcLQ.png I want to clip a square shape f ...

Display the same data point on a Google Map from two different rows of a database

I'm looking to display multiple values for profFName and profLName on a map with just one point showing this information. If I have (2) pID connected to the same marker, I want it to show both profFName and profLName on a single point. Currently, it ...

The function react__WEBPACK_IMPORTED_MODULE_0___default.a.useContext is not recognized when implementing Autocomplete within Material UI

Every time I attempt to create an Autocomplete tag utilizing Material UI, an error pops up, which can be seen in the following link: https://i.sstatic.net/kxKR4.png The Autocomplete code snippet is as follows: import React, {useState, useEffect, useCo ...

Adjust the sizes of the points according to the level of zoom

I've been working on creating a dynamic map in d3.js that displays US Science funding agencies as points, with their sizes scaling based on zoom level. I referred to this starter kit for guidance. While there are other solutions out there, they often ...