반응형
Vue 전문가라면 three.js의 예제 코드를 사용함에 그렇게 문제는 되지 않을 것이다.
하지만 초급 Vue 개발자라면 three.js를 사용할 때 당황할 수도 있다.
이번에는 초급 Vue개발자가 three.js 예제 코드를 사용할 때 팁이 될 만한 정보를 공유하고자 한다.
초급 Vue 개발자가 three.js로 개발시 기존 예제 코드 활용 방법
https://threejs.org/ 에 방문하면 다양한 정보를 얻을 것이다.
Three.js – JavaScript 3D Library
threejs.org
위 사이트에서 예제도 함께 얻을 수 있는 방법이 있다.
Vue파일로 전환할 예제는 아래 캡처, 탱탱볼 예제이다.
위 출처 사이트에 들어가면 소스와 설명을 다 얻을 수 있으니 참고하면 된다.
Vue파일로 전환하기 위해서는 먼저 새로운 Vue 파일을 하나 만들고
캡처 사진 속 JS, HTML, CSS 버튼에 숨겨있는 소스를 복사하여 붙여 넣기를 하면 된다.
아니면 export 버튼을 누르고 알맞는 도구에서 소스를 확인하여 붙여 넣어도 된다.
<template>
//html 버튼 소스 붙여넣기
</template>
<script>
//js 버튼 소스 붙여넣기(vue의 문법에 따라)
</script>
<style scoped>
//css 버튼 소스 붙여넣기
</style>
위와 같이 새로 만든 Vue 파일에 해당 영역에 예제 코드를 붙여넣으면 완료된다.
특히 <script> 영역에서는 Vue 스타일에 맞게 변경하여 코드를 붙여 넣어야 한다.
붙여 넣기 완료된 코드는 다음과 같다.
테스트하면서 약간 수정한 부분이 있으니 찾아보면 도움이 될 수도 있을 것이다.
<template>
<div>
<canvas id="c"></canvas>
</div>
</template>
<script>
import * as THREE from 'three';
export default {
mounted(){
this.initDraw()
},
methods: {
initDraw(){
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 45;
const aspect = 2;
const near = 0.1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
camera.lookAt(0, 0, 0);
const scene = new THREE.Scene();
scene.background = new THREE.Color('white');
const loader = new THREE.TextureLoader();
{
const planeSize = 40;
const texture = loader.load('https://threejs.org/manual/examples/resources/images/checker.png');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.magFilter = THREE.NearestFilter;
const repeats = planeSize / 2;
texture.repeat.set(repeats, repeats);
const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshBasicMaterial({
map: texture,
// side: THREE.DoubleSide,
side: THREE.BackSide,
});
// planeMat.color.setRGB(1.5, 1.5, 1.5);
planeMat.color.setRGB(1, 1, 1);
const mesh = new THREE.Mesh(planeGeo, planeMat);
mesh.rotation.x = Math.PI * -.5;
scene.add(mesh);
}
const shadowTexture = loader.load('https://threejs.org/manual/examples/resources/images/roundshadow.png');
const sphereShadowBases = [];
{
const sphereRadius = 1;
const sphereWidthDivisions = 32;
const sphereHeightDivisions = 16;
const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
const planeSize = 1;
const shadowGeo = new THREE.PlaneGeometry(planeSize, planeSize);
const numSpheres = 17;
for (let i = 0; i < numSpheres; ++i) {
const base = new THREE.Object3D();
scene.add(base);
const shadowMat = new THREE.MeshBasicMaterial({
map: shadowTexture,
transparent: true,
depthWrite: false,
});
const shadowMesh = new THREE.Mesh(shadowGeo, shadowMat);
shadowMesh.position.y = 0.001;
shadowMesh.rotation.x = Math.PI * -.5;
const shadowSize = sphereRadius * 4;
shadowMesh.scale.set(shadowSize, shadowSize, shadowSize);
base.add(shadowMesh);
const u = i / numSpheres;
const sphereMat = new THREE.MeshPhongMaterial();
sphereMat.color.setHSL(u, 1, .75);
const sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
sphereMesh.position.set(0, sphereRadius + 2, 0);
base.add(sphereMesh);
sphereShadowBases.push({base, sphereMesh, shadowMesh, y: sphereMesh.position.y});
}
}
{
const skyColor = 0xB1E1FF; // light blue
const groundColor = 0xB97A20; // brownish orange
const intensity = 0.25;
const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
scene.add(light);
}
{
const color = 0xFFFFFF;
const intensity = 0.75;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(0, 10, 5);
light.target.position.set(-5, 0, 0);
scene.add(light);
scene.add(light.target);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
resizeRendererToDisplaySize(renderer);
{
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
sphereShadowBases.forEach((sphereShadowBase, ndx) => {
const {base, sphereMesh, shadowMesh, y} = sphereShadowBase;
const u = ndx / sphereShadowBases.length;
const speed = time * .2;
const angle = speed + u * Math.PI * 2 * (ndx % 1 ? 1 : -1);
const radius = Math.sin(speed - ndx) * 10;
base.position.set(Math.cos(angle) * radius, 0, Math.sin(angle) * radius);
const yOff = Math.abs(Math.sin(time * 2 + ndx));
sphereMesh.position.y = y + THREE.MathUtils.lerp(-2, 2, yOff);
shadowMesh.material.opacity = THREE.MathUtils.lerp(1, .25, yOff);
});
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
}
}
</script>
<style scoped>
#c {
width: 100%;
height: 100%;
display: block;
}
</style>
반응형
'dev' 카테고리의 다른 글
Vue + axios get parameter 예제 코드 (0) | 2023.05.23 |
---|---|
Vue3 + three.js optimization 예제 코드 (0) | 2023.05.11 |
18. Vue3 + D3.js 코로나 감염 공공데이터 예제 코드 최종 (0) | 2023.05.05 |
17. Vue3 + Node.js 코로나 감염 데이터 가져오기 (0) | 2023.04.19 |
16. Vue3 + D3.js 코로나 감염 지도 python 3으로 공공데이터 가져오기 (1) | 2023.04.19 |