「three.js」3D오브젝트에 mousemove이벤트 적용하기
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값이 추가되는 장면을 볼 수 있다.