Mouseleave в three.js - PullRequest
       28

Mouseleave в three.js

0 голосов
/ 19 марта 2019

Я новичок в Three.js и провел эксперимент, в котором я создал несколько сфер и попытался применить их к эффекту "зависания".Поэтому, когда вы помещаете мышь в сферу, она становится больше, а когда вы покидаете мышь из сферы, она становится меньше.

Вот что я придумал:

    //Scene
var scene = new THREE.Scene();

//Camera
var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
camera.position.z = 10;


//Renderer
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor("#F4F4F4");
renderer.setSize(window.innerWidth,innerHeight);

document.body.appendChild(renderer.domElement);

window.addEventListener('resize', () => {
  renderer.setSize(window.innerWidth,window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;

  camera.updateProjectionMatrix();
})

//Orbit Controls
controls = new THREE.OrbitControls(camera, renderer.domELement);

//Raycaster
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();


//Creating my Spheres
//Shape variable
var geometry = new THREE.SphereGeometry(1, 10, 10);
//Material variable
var material = new THREE.MeshNormalMaterial({wireframe: true});

//loop to create multiple spheres
meshX = -10;
for (var i = 0; i<15; i++) {

  var mesh = new THREE.Mesh(geometry, material);

  mesh.position.x = (Math.random() - 0.5) * 10;
  mesh.position.y = (Math.random() - 0.5) * 10;
  mesh.position.z = (Math.random() - 0.5) * 10;
  scene.add(mesh);
  meshX+=1;
}

//Light
var light = new THREE.PointLight(0xFFFFFF, 1, 500)
light.position.set(10,0,25);
scene.add(light);

//Call the Render method on the renderer
var render = function() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}

//Mouse Over 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);

  var intersects = raycaster.intersectObjects(scene.children, true);
  for ( var i = 0; i < intersects.length; i++ ) {
    this.tl = new TimelineMax();
    this.tl.to(intersects[i].object.scale, 1, {x: 2, y: 2, z: 2, ease: Expo.easeOut})
  }
}

//Mouse Leave Animation
function onMouseLeave(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);
  for ( var i = 0; i < intersects.length; i++ ) {
    this.tl = new TimelineMax();
    this.tl.to(intersects[i].object.scale, 1, {x: 1, y: 1, z: 1, ease: Expo.easeOut})
  }
}

//Event Listener
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseleave', onMouseLeave);
render();

https://jsfiddle.net/xaviergodbout/evdxLbk8/13/

Теперь проблема, с которой я сталкиваюсь в этом решении, заключается в том, что я не могу включить анимацию "mouseleave ".

Я также попробовал THREEx.domevents.js в качестве альтернативы.Я смог создать нужную анимацию при наведении, но я не смог применить ее ко всем сферам.Только один затронут.Я не смог создать JSFiddle для этого, так вот как это выглядит и код: GIF Предварительный просмотр того, что происходит с THREEx.domevents.js

        //Scene
    var scene = new THREE.Scene();

    //Camera
    var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
    camera.position.z = 300;


    //Renderer
    var renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setClearColor("#F4F4F4");
    renderer.setSize(window.innerWidth,innerHeight);

    document.body.appendChild(renderer.domElement);

    window.addEventListener('resize', () => {
        renderer.setSize(window.innerWidth,innerHeight);
        camera.aspect = window.innerWidth / innerHeight;

        camera.updateProjectionMatrix();
    })

    controls = new THREE.OrbitControls(camera, renderer.domELement);

    //Creating a sphere
        //Shape variable
        var aCircles = [];
        var geometry = new THREE.SphereGeometry(20, 20, 20);
        //Material variable
        var material = new THREE.MeshNormalMaterial({wireframe: true});

        for (var i = 0; i < 15; i++) {

            var mesh = new THREE.Mesh(geometry, material);

            mesh.position.x = (Math.random() - 0.5) *200;
            mesh.position.y = (Math.random() - 0.5) *200;
            mesh.position.z = (Math.random() - 0.5) *200;
            scene.add(mesh);
            aCircles.push(mesh);
        }


        var light = new THREE.PointLight(0xFFFFFF, 1, 500)
        light.position.set(10,0,25);
        scene.add(light);

    var domEvents = new THREEx.DomEvents(camera, renderer.domElement)
    var url     = 'http://xaviergodbout.com/'
    var linkify = THREEx.Linkify(domEvents, mesh, url, true)

    var sphereClicked = false  
    domEvents.addEventListener(mesh, 'click', event => {  
        if (!sphereClicked) {
            material.wireframe = false
            sphereClicked = true
        } else {
            material.wireframe = true
            sphereClicked = false
        }
    })

    domEvents.addEventListener(mesh, 'mouseover', event => {  
        this.tl = new TimelineMax();
        this.tl.to(this.mesh.scale, 1, {x: 2, ease: Expo.easeOut, y: 2, ease: Expo.easeOut, z: 2, ease: Expo.easeOut})
    })

    domEvents.addEventListener(mesh, 'mouseout', event => {  
        this.tl = new TimelineMax();
        this.tl.to(this.mesh.scale, 1, {x: 1, ease: Expo.easeOut, y: 1, ease: Expo.easeOut, z: 1, ease: Expo.easeOut})
    })

    domEvents.addEventListener(mesh, 'dblclick', event => {  
        this.tl = new TimelineMax();
        this.tl.to(this.mesh.scale, 1, {x: 5, ease: Expo.easeOut, y: 5, ease: Expo.easeOut, z: 5, ease: Expo.easeOut})
    })

    //Call the Render method on the renderer
    var render = function() {
        requestAnimationFrame(render);
        renderer.render(scene, camera);

        mesh.rotation.y += 0.01
    }

    render();

Любая помощьбыл бы очень признателен с этим.Заранее спасибо!

1 Ответ

0 голосов
/ 19 марта 2019

Вы не должны подписываться window.addEventListener('mouseleave', onMouseLeave); потому что он не будет срабатывать, когда мышь покидает объект.

Исправить # 1 - удалить window.addEventListener('mouseleave', onMouseLeave);

Исправить # 2 - проанализировать результаты raycaster.intersectObjects(scene.children, true); и обработать коллекцию обнаруженных объектов вручную, чтобы определить, какой объект был обнаружен при каждом движении мыши.

Обновленную скрипку вы найдете здесь: https://jsfiddle.net/mmalex/c7t6b1ze/

Фиксированный код:

var hoveredObjects = {};

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);

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

    // collect array of uuids of currently hovered objects
    var hoveredObjectUuids = intersects.map(el => el.object.uuid);

    for (let i = 0; i < intersects.length; i++) {
        var hoveredObj = intersects[i].object;
        if (hoveredObjects[hoveredObj.uuid]) {
            continue; // this object was hovered and still hovered
        }

        this.tl = new TimelineMax();
        this.tl.to(intersects[i].object.scale, 1, {
            x: 2,
            ease: Expo.easeOut,
            y: 2,
            ease: Expo.easeOut,
            z: 2,
            ease: Expo.easeOut
        });

        // collect hovered object
        hoveredObjects[hoveredObj.uuid] = hoveredObj;
    }

    for (let uuid of Object.keys(hoveredObjects)) {
        let idx = hoveredObjectUuids.indexOf(uuid);
        if (idx === -1) {
            // object with given uuid was unhovered
            let unhoveredObj = hoveredObjects[uuid];
            delete hoveredObjects[uuid];

            this.tl = new TimelineMax();
            this.tl.to(unhoveredObj.scale, 2, {
                x: 1,
                ease: Expo.easeOut,
                y: 1,
                ease: Expo.easeOut,
                z: 1,
                ease: Expo.easeOut
            });

        }
    }
}
...