阿超
>
threejs+vite+ts实现官网基础部分
一个温柔的目光,一句由衷的话语,能使人忍受生活给他的许多磨难。——高尔基
官方文档:
three.js manual
源代码从这里改进:
GitHub - PacktPublishing/Learn-Three.js-Fourth-edition: Learn Three.js, Fourth edition, published by Packt
我本地进行了一些修改,首先package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { "name": "three-ts", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview" }, "devDependencies": { "@types/three": "^0.146.0", "typescript": "^4.6.4", "vite": "^3.2.3" }, "dependencies": { "three": "^0.146.0" } }
|
tsconfig.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "lib": ["ESNext", "DOM"], "moduleResolution": "Node", "strict": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "noEmit": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "skipLibCheck": true }, "include": ["src"] }
|
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vite + TS</title> </head> <body> <canvas id="c"></canvas> <script type="module" src="/src/main.ts"></script> </body> </html>
|
src/main.ts
1 2 3 4 5 6 7
| import './style.css' import { initThreeJsScene } from './threeCanvas'
const mainElement = document.querySelector<HTMLDivElement>('#c') if (mainElement) { initThreeJsScene(mainElement) }
|
src/style.css
1 2 3 4 5 6 7 8 9
| html, body { margin: 0; height: 100%; } #c { width: 100%; height: 100%; display: block; }
|
src/threeCanvas.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import * as THREE from "three";
export const initThreeJsScene = (canvas: HTMLDivElement) => { const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
const fov = 75; const aspect = 2; const near = 0.1; const far = 5; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
{ const color = 0xffffff; const intensity = 3; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-1, 2, 4); scene.add(light); }
const boxWidth = 1; const boxHeight = 1; const boxDepth = 1; const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
function makeInstance(geometry: THREE.BoxGeometry, color: number, x: number) { const material = new THREE.MeshPhongMaterial({ color });
const cube = new THREE.Mesh(geometry, material); scene.add(cube);
cube.position.x = x;
return cube; }
const cubes = [ makeInstance(geometry, 0x44aa88, 0), makeInstance(geometry, 0x8844aa, -2), makeInstance(geometry, 0xaa8844, 2), ];
function resizeRendererToDisplaySize(renderer: THREE.WebGLRenderer) { const canvas = renderer.domElement; const pixelRatio = window.devicePixelRatio; const width = canvas.clientWidth * pixelRatio | 0; const height = canvas.clientHeight * pixelRatio | 0; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; }
function render(time: number) { time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) { const canvas = renderer.domElement; camera.aspect = canvas.clientWidth / canvas.clientHeight; camera.updateProjectionMatrix(); }
cubes.forEach((cube, ndx) => { const speed = 1 + ndx * 0.1; const rot = time * speed; cube.rotation.x = rot; cube.rotation.y = rot; }); renderer.render(scene, camera);
requestAnimationFrame(render); } requestAnimationFrame(render); };
|
效果大致如下: