Dat GUI
Video Lecture
Description
The Dat GUI is another very useful tool that we can use to learn about Three.js as it allows us to quickly add a very basic user interface which allows us to interact with our 3d scene and the objects within it.
The Three.js install includes a copy of dat.gui.module.js
so we will use that.
However, the version of Three.js at the time of writing this lesson, doesn't include a type definition file for dat.gui.module.js
by default.
Manually install the type definition file.
1 | npm install @types/dat.gui |
The installed type definition file will not auto link with the dat.gui.module.js
in the Three.js library folder just yet. See the section below at ./src/client/tsconfig.json
Final Scripts
./src/client/client.ts
Add the Dat.GUI import and usage to the ./src/client/client.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 | import * as THREE from '/build/three.module.js' import { OrbitControls } from '/jsm/controls/OrbitControls' import Stats from '/jsm/libs/stats.module' import { GUI } from '/jsm/libs/dat.gui.module' const scene: THREE.Scene = new THREE.Scene() var axesHelper = new THREE.AxesHelper( 5 ); scene.add( axesHelper ); const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer() renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement) const controls = new OrbitControls(camera, renderer.domElement) //controls.addEventListener('change', render) const geometry: THREE.BoxGeometry = new THREE.BoxGeometry() const material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true }) const cube: THREE.Mesh = new THREE.Mesh(geometry, material) scene.add(cube) camera.position.z = 2 window.addEventListener('resize', onWindowResize, false) function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) render() } const stats = Stats() document.body.appendChild(stats.dom) const gui = new GUI() const cubeFolder = gui.addFolder("Cube") cubeFolder.add(cube.rotation, "x", 0, Math.PI * 2, 0.01) cubeFolder.add(cube.rotation, "y", 0, Math.PI * 2, 0.01) cubeFolder.add(cube.rotation, "z", 0, Math.PI * 2, 0.01) cubeFolder.open() const cameraFolder = gui.addFolder("Camera") cameraFolder.add(camera.position, "z", 0, 10, 0.01) cameraFolder.open() var animate = function () { requestAnimationFrame(animate) //cube.rotation.x += 0.01; //cube.rotation.y += 0.01; render() stats.update() }; function render() { renderer.render(scene, camera) } //render() animate(); |
./src/server/server.ts
Add the static route to the NodeJS Express server so that it knows which file to return to it when it is asked for it by the client,
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 | import http from "http" import path from "path" import express from "express" const port: number = 3000 class App { private server: http.Server private port: number constructor(port: number) { this.port = port const app = express() app.use(express.static(path.join(__dirname, '../client'))) app.use('/build/three.module.js', express.static(path.join(__dirname, '../../node_modules/three/build/three.module.js'))) app.use('/jsm/controls/OrbitControls', express.static(path.join(__dirname, '../../node_modules/three/examples/jsm/controls/OrbitControls.js'))) app.use('/jsm/libs/stats.module', express.static(path.join(__dirname, '../../node_modules/three/examples/jsm/libs/stats.module.js'))) app.use('/jsm/libs/dat.gui.module', express.static(path.join(__dirname, '../../node_modules/three/examples/jsm/libs/dat.gui.module.js'))) this.server = new http.Server(app); } public Start() { this.server.listen(this.port, () => { console.log(`Server listening on Port ${this.port}.`) }) } } new App(port).Start() |
./src/client/tsconfig.json
You have several options here to correct the missing type definition reference.
One option is to manually copy the file index.d.ts
from the node_modules/@types/dat.gui
folder into the node_modules/three/examples/jsm/libs
folder and rename it to dat.gui.module.d.ts
.
or
add a path to the ./src/client/tsconfig.json
that indicates to the VSCode IDE and TypeScript compiler which type definition to use when it sees the import to /jsm/libs/dat.gui.module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "compilerOptions": { "target": "ES6", "module": "ES6", "outDir": "../../dist/client", "baseUrl": ".", "paths": { "/build/three.module.js": ["../../node_modules/three/src/Three"], "/jsm/*": ["../../node_modules/three/examples/jsm/*"], "/jsm/libs/dat.gui.module": ["../../node_modules/@types/dat.gui"] }, "moduleResolution": "node", "strict": true }, "include": [ "**/*.ts" ] } |