在游览threejs的官方文档的时候,我们会发现他不单单是做了一个3D展示图形,他还提供了一个图形页面,用来控制3D对象的一些属性,在进行操作图形界面时,对应的3D对象物体的属性也会跟着进行改变,如下图:
这时也许你会好奇这个界面时如何做的,这就引入了这篇文章的重点了,也就是dat.gui,首先我们先熟悉一下他是做什么的:
dat.gui 是一个开源的前端 JavaScript 库,用于创建基于 web 界面的交互式调试界面。它提供了一个简单易用的 API,使用户可以轻松地创建各种控件,如滑块、复选框、下拉菜单、颜色选择器等,以便在浏览器中测试和修改代码时进行交互式的实验。
dat.gui GitHub地址:https://github.com/dataarts/dat.gui/blob/HEAD/API.md
GSAP (GreenSock Animation Platform) 是一个 JavaScript 动画引擎,用于为 web 应用程序创建复杂的动态效果和交互式界面。它由 GreenSock 公司推出,是一个功能强大、高性能、易于使用且高度可定制的动画库。
GSAP 提供了一组灵活和强大的 API 让开发人员可以控制元素的属性、时间轴、缓动函数等,并能够在多平台上设计流畅而专业的动画效果,在网站和应用程序中创建出色的用户体验。
gsap官网:https://greensock.com/
这里的话就直接上代码了,也不做过多的说明,其中对这一段代码不够熟悉的话可以查看这个分栏:https://blog.csdn.net/qq_44973159/category_12267425.html
这里新增了一个Orbit controls(轨道控制器),它可以使得相机围绕目标进行轨道运动。并且在最后添加了两个监听事件,其中分别是窗口改变大小后页面自适应&双击全屏&退出全屏展示
import * as THREE from 'three'
import {
OrbitControls
} from 'three/examples/jsm/controls/OrbitControls.js'
var dir = false
// 场景
const scene = new THREE.Scene();
// 相机 (透视相机) 角度、宽高比、近端面、远端面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
scene.add(camera);
// 几何体与材质
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
// 设置位置
cube.position.set(0, 0, 0)
scene.add(cube);
// 渲染
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 新增轨迹控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 阻尼感 新增update()
controls.enableDamping = true
function render(time) {
controls.update()
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
window.addEventListener('resize', (e) => {
// 宽高比
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
})
window.addEventListener('dblclick', () => {
if (!document.fullscreenElement) {
renderer.domElement.requestFullscreen()
} else {
document.exitFullscreen()
}
})
首先需要安装该库
npm i gsap
引入gsap
import gsap from 'gsap'
我们在对应的js当中当中直接使用gsap,如下代码:用于控制一个旋转的立方体 cube 的动画效果。gsap.to() 方法中传入了两个参数。
gsap.to(cube.rotation, {
x: 5 * Math.PI,
duration: 5,
ease: 'power1.inOut'
})
这里定义了一个名为 animation 的常量,它调用了 gsap.to() 方法。方法的第一个参数是要变化属性的对象,即 cube.position,表示需要对立方体的位置进行动态变化。第二个参数是一个配置对象,包含以下选项:
因此,这段代码意味着立方体将沿 x 轴向右移动 5 个单位(每次循环),以一定的缓动方式执行一个连续翻转的动画,并将在循环结束时反转动画并重复播放,直到无限次数。还设置了延迟 2 秒后开始动画效果,并在每次动画开始和完成时弹出相应的警告提示框。
const animation = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: 'power1.inOut',
repeat: -1,
yoyo: true,
delay: 2,
onStart: () => {
alert("动画开始")
},
onComplete: () => {
alert("动画完成")
}
})
在通过对页面的点击事件来进行监听控制:
window.addEventListener('click', () => {
if (animation.isActive()) {
animation.pause()
} else {
animation.resume()
}
})
首先我们还是在一个vue脚手架的项目当中实现,先安装dat.gui库
npm i dat.gui
引入dat.gui
import * as dat from 'dat.gui'
使用dat.gui,在使用之前需要new一个对象实例出来,再通过其add方法,向 GUI 添加新控制器。创建的控制器类型 从 的初始值推断。
在这里是往cube.position 对象上的 x 属性作为一个可调整的控制器,该控制器允许用户更改立方体沿 x 轴的位置。接下来,对该控制器进行了一些定制。使用 .min() 和 .max() 方法设置允许的值的范围,并将步进值设置为 0.01。然后给控制器取了一个名字 ‘移动x轴’。
在链式调用后面,使用 .onChange() 方法传递一个回调函数以响应控制器值的每次更改。当控制器的值发生变化时,回调函数将在控制台中输出消息“值已被修改:”并显示新的控制器值。
通过使用 .onFinishChange() 方法,向该控制器绑定一个另一个回调函数,该函数在用户停止拖动滑块时执行,即完全停止拖动控件以达到新值的过程结束。当该控制器的值不再更改时,此时回调函数将在控制台中输出消息“已完全停止:”并显示当前控制器值。
const GUI = new dat.GUI();
GUI.add(cube.position, 'x').min(0).max(10).step(0.01).name('移动x轴')
.onChange((value) => {
console.log('值被修改:', value)
}).onFinishChange((value) => {
console.log('完全停下来:', value)
})
这里调用 GUI.addColor() 方法来向 GUI 中添加新的颜色控件。该方法接受两个参数:第一个参数是一个包含要控制的初始值的对象,以及其他相关选项,这里设置初始颜色为黑色;第二个参数是控件的名称,可选。
然后使用 .onChange() 方法传递回调函数,以响应控制器值的每次更改。当用户更改控制器的值时,回调函数将在执行时接收所选颜色(由 CSS 颜色字符串表示),然后调用 cube.material.color.set() 方法设置立方体的颜色。
GUI.addColor({
color: '#000'
}, 'color').onChange((value) => {
cube.material.color.set(value)
})
这里调用 GUI.add() 方法,将 cube 对象作为第一个参数传递给它,‘visible’ 作为第二个参数,以此将目标属性添加为可调整的控制器。然后使用 .name() 方法指定该控件的名称为“是否显示”。调用完后,用户可以使用控件上的复选框来切换立方体对象的可见性,从而决定它是否在场景中显示出来。
GUI.add(cube, 'visible').name('是否显示')
点击 GUI 上的“开启动画”按钮时,会触发 gsap.to() 方法,用于设置立方体沿着 x 轴移动的动画。该方法使用 GreenSock 动画引擎 (GSAP) 提供的 API,可以方便地控制动画的各种参数,例如 duration、ease 等。这里设置盒子从当前位置向右偏移 5 个单位,然后返回到原始位置。repeat:1 意味着重复一次完整动画, yoyo:true 表示在动画结束后,反向回播动画一遍。
GUI.add({
fn: function () {
gsap.to(cube.position, {
x: 5,
duration: 5,
ease: 'power1.inOut',
repeat: 1,
yoyo: true
})
}
}, 'fn').name('开启动画')
调用 GUI.addFolder() 方法来向 GUI 中添加新的文件夹控件。该方法接受一个参数,即此文件夹的名称。然后在文件夹中调用 folder.add() 方法两次。
第一次调用将 cube.position.z 添加至文件夹中,并指定控制器的最小值为 0,最大值为 10,步长为 0.01。 .name() 方法设置控制器的显示名称为“移动z轴”。通过这种方式,可以轻松修改立方体对象沿 z 轴的位置。
第二次调用将 cube.material.wireframe (线框属性)添加到文件夹中,并使用 .name() 方法指定控制器名称为“线框”。这样就可以通过单击控制台上的复选框来切换立方体对象的网格线框架可见性。
const folder = GUI.addFolder('文件夹(设置子操作)')
folder.add(cube.position, 'z').min(0).max(10).step(0.01).name('移动z轴')
folder.add(cube.material,"wireframe").name('线框')