웹개발 자료실/three.js 프론트개발 Code

「three.js」3D오브젝트에 mousemove이벤트 적용하기

Recstasy 2023. 1. 13. 09:05

 

 

 

 

 

1) 파란색 공을 5 x 5 배열 형태로(높이는 없음) 나열한다

2) 사용자가 마우스를 공에 가져간다

3) 공들이 하늘로 떠오른다

 

 

 

 

 


|  공 생성하기

파란색 공은 'SphereGeometry'로 생성할 수 있다. 씬 제작에 필요한 scene, camera, light, renderer 그리고 3D 오브젝트를 담을 변수를 만들어준다.

 

let scene, camera, renderer, sphere, light1, rayCast, control;
let mouse = new THREE.Vector2();
let ele = document.getElementById('wd-mousemove');
let objects = [];
let ADD = 0.5;
let theta = 0;

let init = function () {

        scene = new THREE.Scene();
        scene.background = new THREE.Color( 0x000000);

        camera = new THREE.PerspectiveCamera( 75, ele.clientWidth / ele.clientHeight, 0.1, 1000 );
        camera.position.set( 50, 10, 70 );

        light1 = new THREE.DirectionalLight( 0xffffff, 1 );
        scene.add( light1 );

     // createGeometry();

        renderer = new THREE.WebGLRenderer();
        renderer.setSize ( ele.clientWidth, ele.clientHeight );

        ele.appendChild( renderer.domElement );

        control = new OrbitControls( camera, renderer.domElement );
        control.update();
        
        ele.addEventListener( 'resize', onWindowResize, false );

    }

    function onWindowResize() {
        camera.aspect = ele.clientWidth / ele.clientHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( ele.clientWidth, ele.clientHeight );
    }

    let mainLoop = function () {
        requestAnimationFrame( mainLoop );
        renderer.render( scene, camera );
    }
    
    init();
    mainLoop();

 

 

우선 위와 같이 skeleton을 실행해서 3D 뷰가 나오는지 확인한다.

 

 

 

 

 

 


| rayCast 설정

init()함수의 renderer코드가 있는 부근에 Raycaster()인스턴스를 생성한다. Raycaster()는 인자값으로 mouse, camera가 필수적이므로 mousemove이벤트에서 사용될 mouse 2차원 벡터값을 확인해준다.(임시 -1, -1 입력) 

 

// init()함수 
// 중략..

rayCast = new THREE.Raycaster();
mouse.x = mouse.y = -1;

// 중략..

 

 

 

 

 


|  마우스무브 이벤트

init()함수의 거의 끝줄에 mousemove이벤트는 화면 컨트롤 다음 줄에 넣어준다. 이벤트 코드는 renderer설정 이후가 적당하다. 

 

// init()함수
// 중략..

    renderer.domElement.addEventListener('mousemove', onMouseMove, false);
}

let onMouseMove = function(e) { 

    e.preventDefault();
    let gapX = e.clientX - e.offsetX; 
    let gapY = e.clientY - e.offsetY;

    mouse.x = ( (e.clientX - gapX ) / ele.clientWidth ) * 2 - 1;
    mouse.y = -( (e.clientY - gapY) / ele.clientHeight ) * 2 + 1;

    rayCast.setFromCamera( mouse, camera )
    let intersect = rayCast.intersectObjects (scene.children );

    intersect.forEach( obj => {
        obj.object.position.y += 1
    });    
}

 

 

마우스가 움직이면 공이 y축으로 움직여야 한다. 따라서 마우스 이벤트 함수는 rayCast.setFromCamera(mouse,camera)메서드를 통해 마우스와 반응하는 화면 내 객체들을 모두 받는다. 위와 같이, rayCast의 intersectObjects()메서드를 이용해 scene의 모든 객체들을 intersect변수에 담는다. 이로써 사용자와 반응한 객체를 제어할 준비를 마쳤다.

 

 

 

 

 

 


| 'Sphere' 설정

이중 for문을 활용해 5x5 메트릭스를 이용한다.

 

let createGeometry = function () {
    
    let k = 2;

    for ( let i = 0; i < 5; i++ ) 
    {
        for (let j = 0; j < 5; j++) 
        {       
            let geometry = new THREE.SphereGeometry( 4, 30, 30 );
            let material = new THREE.MeshPhongMaterial({
                color: 0x0000ff,
                shininess: 100
            });

            sphere = new THREE.Mesh( geometry, material );
            sphere.position.x = i * (k+7) + (k+5);
            sphere.position.z = j * (k+7) + (k+5);
            scene.add(sphere);
        }
    }
}

 

 

위와 같이, i, j 반복문 내에서 sphere의 위치를 이동시켜 준다. 마지막으로 createGeometry함수를 init()함수에 선언한다. 

코드를 실행하면, 사용자의 마우스 커서가 '구'와 접촉할 때마다 파란 공들의 y값이 추가되는 장면을 볼 수 있다.