使用dat.gui 控制threejs(一)
1 import * as THREE from 'three'
2 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
3 import gsap from 'gsap'
4 import * as dat from 'dat.gui'
5 // Canvas
6 const canvas = document.querySelector('canvas.webgl')
7
8 // Scene
9 const scene = new THREE.Scene()
10
11
12 // Object
13 const geometry = new THREE.BoxBufferGeometry(1, 1, 1, 2,2,2)
14 // buffer geometry 集合体是性能最佳,最gpu最友好的 geometry。
15 // BoxGeometry 后面三个参数设置为1, 每一面就划分为2个三角形 triangle, 2 就得到八个
16
17 // 自定义一个geometry
18 // const geometry = new THREE.BufferGeometry();
19 // const vertices = new Float32Array([
20 // 0,0,0,
21 // 0,1,0,
22 // 1,0,0
23 // ])
24 // geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
25 const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe:false })
26 const mesh = new THREE.Mesh(geometry, material)
27 scene.add(mesh)
28
29 // define a color object
30 const obj = {
31 color:0xff0000,
32 spin:() => {
33 gsap.to(mesh.rotation, {duration:1, y:mesh.rotation.y + 5})
34 }
35 }
36
37 /* debug gui panel*/
38 const gui = new dat.GUI({
39 closed: true,
40 // 表示一开始 panel 先处于关闭状态
41 // width:400 设置panel width
42 })
43 //gui.hide() // 隐藏gui panel
44
45 gui.add(mesh.position, 'y', -3, 3, 0.01).name('positon-y') // 使用name() 重命名panel item title
46 gui.add(mesh.position, 'x').min(-3).max(3).step(0.01)// 用链式调用的方式也可以!
47 //设置控制mesh y坐标的panel Item,并且规定控制的最大值3,最小值-1, 移动步长为0.01
48
49 //控制 mesh 的属性 ,比如 visible:mesh 是否可见
50 gui.add(mesh, 'visible')
51 gui.add(material,'wireframe')
// dat.gui 改变obj的颜色时,将材质的颜色一并替换
52 gui.addColor(obj, 'color').onChange(() => {
53 material.color.set(obj.color)
54 })
55 gui.add(obj, 'spin')
56 // animation
57 const animations = () => {
58 gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
59 gsap.to(mesh.position, { duration: 1, delay: 2, x: 0 })
60 }
61 animations()
62 // Sizes
63 const sizes = {
64 width: window.innerWidth,
65 height: window.innerHeight
66 }
67
68 // Camera
69 const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
70 camera.position.z = 3
71 scene.add(camera)
72
73 // controls
74
75 const controls = new OrbitControls(camera, canvas);
76 controls.enableDamping = true
77 //开启阻尼,也就是惯性, 然后需要在每一帧进行controls.update()
78 //
79 // controls.target.y = 2 //controls target 指向的是对象围绕的焦点
80 // controls.update()
81
82 // Renderer
83 const renderer = new THREE.WebGLRenderer({
84 canvas: canvas
85 })
86 const tick = () => {
87 controls.update()
88 renderer.render(scene, camera)
89 window.requestAnimationFrame(tick)
90 // 动画一定需要配合帧动画请求!!!
91 }
92 tick()
93 let cursor = {
94 x:0,
95 y:0
96 }
97 // 绑定鼠标事件
98 window.addEventListener('mousemove', (event) => {
99 // 这样子会使得x,y 坐标值会归于(-0.5-0.5 这个区间),
100 cursor.x = event.clientX / sizes.width - 0.5
101 cursor.y = -(event.clientY / sizes.height - 0.5)
102 // 不加符号,会使得鼠标上下移动的时候,mesh看起来是跟随鼠标方向的,但是其实移动相机,mesh最终效果是要跟鼠标反向运动(相机向右,以相机为参照物,其实mesh向左)。
103 //camera.position.x = cursor.x
104 //camera.position.y = cursor.y
105
106 // 让相机围绕着mesh 旋转(首先要清楚 这里实现旋转,改变位置的话,是 x和z方向旋转)
107 // camera.position.x = Math.sin(cursor.x * Math.PI * 2) * 3
108 // camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 3
109 // camera.position.y = cursor.y * 6
110 // camera.lookAt(mesh.position)
111 })
112
113 //window resize handle
114 window.addEventListener('resize', () => {
115 sizes.width = window.innerWidth
116 sizes.height = window.innerHeight
117
118 camera.aspect = sizes.width / sizes.height
119 camera.updateProjectionMatrix()
120 //修改相机参数后,需要统计threejs 去更改 projectMatrix, 项目矩阵?
121
122 //renderer 修改画布的size
123 renderer.setSize(sizes.width, sizes.height)
124 renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
125 })
126
127 // 绑定全屏事件
128 window.addEventListener('dblclick', () => {
129 // 注意,这个特性,对于 safari 浏览器无效
130 // if(!document.fullscreenElement) {
131 // canvas.requestFullscreen()
132 // }else {
133 // document.exitFullscreen()
134 // }
135
136 //最终兼容写法
137 const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement
138 if(!fullscreenElement) {
139 if(canvas.requestFullscreen) {
140 canvas.requestFullscreen()
141 }else if(canvas.webkitRequestFullscreen) {
142 canvas.webkitRequestFullscreen()
143 }
144 }else {
145 if(document.exitFullscreen) {
146 document.exitFullscreen()
147 }else if(document.webkitExitFullscreen) {
148 document.webkitExitFullscreen()
149 }
150 }
151 })
152
153 renderer.setSize(sizes.width, sizes.height)
154 // 规定渲染器,设定像素比 为1 or 2 有益于性能!!!
155 renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))