Using three.js and gsap to create interactive mousemove effects

I've been attempting to create a mousemove event that scales the mesh when the mouse hovers over it, and returns it to its original size when the mouse is no longer hovering. I've looked at examples that use tween.js instead of gsap, but my syntax might be incorrect.

Here's the function I'm using:

function onMouseMove(event) {
 //finding position of mouse
                event.preventDefault();
                mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
                raycaster.setFromCamera(mouse,camera);

      // meshes included in mousemove
                objects.push( mesh);
                objects.push( mesh2 );

//including objects into intersects

                var intersects = raycaster.intersectObjects(objects, true);

    //if statement for intersection
                if ( intersects.length > 0 ) {

                    if ( intersects[ 0 ].object != INTERSECTED ) 
                    {
                        if ( INTERSECTED ) 
//gsap animation
                            INTERSECTED.gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
                            INTERSECTED = intersects[ 0 ].object;


                    }
                } else {// there are no intersections 
                        // restore previous intersection object to its original size
                        if ( INTERSECTED ) 
                        gsap.to(intersects[0].object.scale, {duration: .7, x: 1, y:1});

                            INTERSECTED = null;

                }
            }

When implementing this function, I encounter an error: Cannot read property 'object' of undefined at onMouseMove

The code does work with a for loop that involves undefined object, but I need it to scale down again once the mouse moves away.

Here's the for loop I used:

 for(var i = 0; i < intersects.length; i++) {
                    gsap.to(intersects[i].object.scale, {duration: .7, x: 1.2, y:1.2});
                };

EDIT:

I have created a fiddle utilizing the for loop while commenting out the if statement:

let camera, scene, renderer, cube, cube1;
let raycaster;
let mouse = new THREE.Vector2(), INTERSECTED;
const objects = [];


init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 );
    camera.position.z = 20;

    scene = new THREE.Scene();

    const geometry = new THREE.BoxBufferGeometry(3,3,3);
    const material = new THREE. MeshBasicMaterial({ color: 0x00ff00 });
     cube = new THREE.Mesh(geometry, material);
     cube.position.y = 5;
    
    scene.add(cube);
    
    
    const geometry1 = new THREE.BoxBufferGeometry(3,3,3);
    const material1 = new THREE. MeshBasicMaterial({ color: 0x00ff00 });
     cube1 = new THREE.Mesh(geometry1, material1);
    
    scene.add(cube1);
    
    raycaster = new THREE.Raycaster();
     renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    
    window.addEventListener('mousemove',onMouseMove, false);


}

    

// animation
    
   function onMouseMove (event) {

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

  //included in mousemove
 
objects.push( cube );
            objects.push( cube1 );

   
  var intersects = raycaster.intersectObjects(objects, true);
  
//working for loop
   for(var i = 0; i < intersects.length; i++) {
        gsap.to(intersects[i].object.scale, {duration: .7, x: 1.2, y:1.2});
    }
    

    //not working if statement
    
    /*     
                if ( intersects.length > 0 ) {

                    if ( intersects[ 0 ].object != INTERSECTED ) 
                    {
                        if ( INTERSECTED ) 
                            INTERSECTED.gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
                            INTERSECTED = intersects[ 0 ].object;
                            
                            
                    }
                } else {// there are no intersections 
                        // restore previous intersection object (if it exists) to its original size
                        if ( INTERSECTED ) 
                        gsap.to(intersects[0].object.scale, {duration: .7, x: 1.2, y:1.2});
                       
                            INTERSECTED = null;
    
                }
                */
               
   }

   
   
   
function animate() {

  


    requestAnimationFrame( animate );
    renderer.render( scene, camera );

}
body {
  margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e89c809aababedcadb88e58a87">[email protected]</a>/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6e14d41304d0e90434221155415">[email protected]</a>/dist/gsap.js"></script>

Answer №1

Give this updated code a shot:

let camera, scene, renderer, box1, box2;
let raycaster;
let cursor = new THREE.Vector2(), target = null;
const objectsArr = [];


setup();
startAnimation();

function setup() {

camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.z = 20;

scene = new THREE.Scene();

const geo1 = new THREE.BoxBufferGeometry( 3, 3, 3 );
const mat1 = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
box1 = new THREE.Mesh( geometry, material );
box1.position.y = 5;

scene.add( box1 );

const geo2 = new THREE.BoxBufferGeometry( 3, 3, 3 );
const mat2 = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
box2 = new THREE.Mesh( geometry1, material1 );

scene.add( box2 );

raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

window.addEventListener( 'mousemove', trackCursor, false );

}

function trackCursor( event ) {

event.preventDefault();
cursor.x = ( event.clientX / window.innerWidth ) * 2 - 1;
cursor.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( cursor, camera );

objectsArr.push( box1 );
objectsArr.push( box2 );

var intersects = raycaster.intersectObjects( objectsArr, true );

if ( intersects.length > 0 ) {
var object = intersects[ 0 ].object;

if ( object !== target ) {
target = object;
gsap.to( target.scale, { duration: .7, x: 1.2, y: 1.2 } );
}

} else {

if ( target !== null ) {
gsap.to( target.scale, { duration: .7, x: 1, y: 1 } );
target = null;
}

}

}

function startAnimation() {

requestAnimationFrame( startAnimation );
renderer.render( scene, camera );

}
body {
  margin: 0;
}
canvas {
    display: block;
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="24504c56414164140a151510">[email protected]</a>/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3a5d495b4a7a091408140e">[email protected]</a>/dist/gsap.js"></script>

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

The 'X' property is not found in the DefaultRootState type, even though it is declared in the corresponding Interface

Below is the Interface being used in conjunction with mapStateToProps: export interface IStore { cache?: any; dataManager?: IUR; userPrefs: IUP; IModal?: IfingerprintModal; } export interface IModal { cbCancel: IFModalFn | null; cbTryAgain?: I ...

When the form is submitted, I am unable to record the checkbox value

Hi, I have a question regarding submitting a form to the "/delete" route when a checkbox is checked. Although I am able to submit the form successfully, I am facing an issue retrieving the checkbox value that I assigned using ejs. Below are the relevant co ...

Setting value in Angular's ng-repeat directive

Utilizing ng-repeat, I am creating a table with radio buttons. The main goal is to assign each radio button a value based on the position of the object in the original array (before any sorting takes place). However, using $index assigns the position in ...

Guide to attaching data to an AJAX request

I'm new to ajax and recently encountered an issue while working on a project where I needed to send a query from an HTML form. However, I've been unable to send any data for some reason. I tried sending FormData through the xmlhttprequest.send() ...

The value of the parameter '<' has been converted to '<'

I am currently utilizing ExpressJS in conjunction with the body-parser library. Upon passing a parameter value of 2<5, it is observed to be altered and converted to 2&lt;5 read: async (req, res, next) => { try { let condition= req.q ...

Explain the functionality of the pow function in glsl

I've been exploring the site: Currently, I am delving into this code, but I'm struggling to grasp how the pow function is influencing the line's behavior when different values are plugged in: // Created by: Inigo Quiles // Titled: Expo ...

There was an uncaught error in AngularJS stating that the URL in the HTTP request configuration must be a string

I've been working on a web application and have encountered some challenges. One particular issue I'm struggling with is related to the following code snippet: this.bookSpace = function (date, spaceId) { swal({ title: "Are you sure?", t ...

A guide on executing a double click action on an element in Selenium Webdriver with JavaScript specifically for Safari users

Having trouble double clicking an element in Safari using Java / Webdriver 2.48. All tests work fine on IE, Chrome, and Firefox but Safari does not support Actions. Currently attempting: executor.executeScript("arguments[0].dblclick();", element); or ...

Ways to resolve eslint typedef error when using angular reactive forms with form.value

I am facing an issue with my formGroup and how I initialized it. Whenever I try to retrieve the complete form value using form.value, I encounter an eslint error related to typecasting. userForm = new FormGroup<user>({ name: new FormControl<st ...

Utilizing ESLint to Conditionally Import External Packages

I'm attempting to bring in a package and utilize it within my Vue application like so: import ExternalSamplePackage from 'external-sample-package' export default { directives: { ExternalSamplePackage } } Since I am in SSR mode, I want ...

jQuery replacement for replaceChild method

I've been attempting to swap out an existing DOM element with a new one that I created. I attempted the following code snippet: $(this).parent().replaceChild(newElem,this); However, it resulted in an error message saying $(this).parent().replaceChi ...

CSS sticky element not preserving its parent's styles

Hello everyone, I need some assistance with a CSS sticky property issue I am encountering. When I apply the sticky property to a div and scroll down, it doesn't retain its parent's properties as expected. Here is the scenario: I have a Bootstrap ...

Discover how to utilize images encoded in base64 format within webhook embeds on Discord

Can someone help me with inserting an image into a Discord embed using a webhook? I have the image saved as a base64 string obtained from a database. However, my attempts so far have only resulted in an empty embed. https://i.sstatic.net/CVs4j.png const d ...

Convert a JSON Object using AngularJs

Is there a method in Angular to restructure this JSON Object? I am looking to convert the JSON object from its original format: $scope.TestJson = { "filters": [ { "dataPropertyID": "VoidType", ...

Creating a dynamic route in Node Express allows for flexible path handling

Is there a way to incorporate a dynamic route or path using the Express package? The challenge is that the path is an ID passed by the client and we have no control over it. const express = require('express'); const dynamicPath = express(); dyn ...

Get the QR code canvas image with a customized background by downloading it

I am having trouble with downloading a QR code canvas image with a background. The download works fine, but my device is unable to scan the code properly due to an incomplete border. I need to add a white background behind it to make it larger. Current im ...

Ways to combine X and Y velocities into a single velocity

Is there a way to combine the X and Y Velocity into a single Velocity without considering the angle? var velocityX = some value; var velocityY = some value; // Need to convert both X and Y velocities into one combined velocity ...

Enhance your <head> section by adding lines when utilizing Layouts within Iron Router

Is there a way to add more lines to the <head> section using Iron Router and layouts? Take for example, inserting the following code snippet into the <head>... <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=ed ...

What is the best way to create a case-insensitive search feature in Node.js?

I have implemented a search function that takes input from the client as Str. If it matches with content in a file, I send that response. For example, if I have text in a file labeled Lorem, and the client searches for lorem, it returns an empty array due ...

Syntax for private members in ES6 classes

I'm curious to know the most efficient way to declare private members within ES6 classes. In simpler terms, what is the best practice for implementing: function MyClass() { var privateFunction = function() { return 0; }; this.publicFuncti ...