制作GUI的两种方法
在本教程中,我们将了解如何创建图形界面,以便能够将数据输入到babylon.js应用程序中。
# GUI模块
GUI文档 (opens new window) npm install -S @babylonjs/gui @babylonjs/materials @babylonjs/gui-editor @babylonjs/serializers
在项目中引入GUI
import * as GUI from '@babylonjs/gui/2D'
简单的创建一个AdvancedDynamicTexture的全屏实例,参数中的字符串只是一个可选的名称
const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI')
现在我们已经准备好了动态纹理实例,现在我们向其中引入元素
# 普通按钮
要做的第一件事是添加一个按钮
const button = GUI.Button.CreateSimpleButton('myBtn', '点我!')
advancedTexture.addControl(button)
2
如图,我们得到了按钮,但按钮的背景不可见,而且它占据了整个画布。
为了解决这个问题,我们需要为按钮设置宽度和高度,因为正常情况下,大多数空间都占用动态纹理的整个宽度和高度
button.width = '200px'
button.height = '40px'
2
我们还可以修改按钮的颜色,颜色名字和css中一样
button.color = 'white'
button.background = 'deepskyblue'
2
# 有背景图的按钮
我们可以创建另一种类型的按钮,这些按钮包含图像
const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI')
const button = GUI.Button.CreateImageButton('myBtn','点我!','vite.svg')
button.width = '200px'
button.height = '40px'
button.color = 'white'
button.background = 'deepskyblue'
advancedTexture.addControl(button)
2
3
4
5
6
7
修改按钮中图片的位置
button.image.left = '30px'
绑定事件
button.onPointerUpObservable.add(function(){
planeMat.emissiveTexture = null
planeMat.emissiveColor = BABYLON.Color3.Teal()
})
2
3
4
# 文本块
可以将文本添加到动态纹理中
const text = new GUI.TextBlock()
text.text = 'Hello World!'
text.color = 'white'
text.fontSize = 72
text.fontFamily = 'Montserrat Black'
text.shadowColor = '#000'
text.shadowOffsetX = 2
text.shadowOffsetY = 2
advancedTexture.addControl(text)
2
3
4
5
6
7
8
9
# 文本输入
const input = new GUI.InputText()
// 宽度为canvas的2%
input.width = 0.2
input.height = '40px'
input.text = 'Default text'
input.color = 'black'
input.background = 'deepskyblue'
input.focusedBackround = 'white'
input.onTextChangedObservable.add(function(value){
planeMat.emissiveTexture = null
planeMat.emissiveColor = new BABYLON.Color3(0, 0, value.text)
})
advancedTexture.addControl(input)
2
3
4
5
6
7
8
9
10
11
12
13
# 滑块
const slider = new GUI.Slider()
slider.minimum = 0
slider.maximum = 1
slider.height = '20px'
slider.width = '200px'
slider.value = 1
slider.onValueChangedPObservable.add(function(value){
planeMat.emissiveTexture = null
planeMat.emissiveColor = new BABYLON.Color3(0, 0, value)
})
advancedTexture.addControl(slider)
2
3
4
5
6
7
8
9
10
11
# 颜色选择器
const picker = new GUI.ColorPicker()
picker.onValueChangedObservable.add(function(value) {
planeMat.emissiveTexture = null
planeMat.emissiveColor.copyFrom(value)
})
advancedTexture.addControl(picker)
2
3
4
5
6
# 单选框
const checkbox = new GUI.Checkbox()
checkbox.width = '20px'
checkbox.height = '20px'
checkbox.color = 'white'
checkbox.isChecked = false
checkbox.onIsCheckedChangedObservable.add(function(value){
planeMat.wireframe = value
})
advancedTexture.addControl(checkbox)
2
3
4
5
6
7
8
9
但这个单选框没有lable,我们来给单选框添加label
const checkboxHeader = GUI.Control.AddHeader(checkbox, 'Wireframe', '100px', {
isHorizontal: true,
controlFirst: false
})
checkboxHeader.color = 'white'
advancedTexture.addControl(checkboxHeader)
2
3
4
5
6
不过有更简单的方式:
const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI')
const cBoxWithHeader = GUI.Checkbox.AddCheckBoxWithHeader('Wireframe:', function(value) {
planeMat.wireframe = value
})
cBoxWithHeader.children[0].isChecked = false
cBoxWithHeader.children[1].fontSize = 38
advancedTexture.addControl(cBoxWithHeader)
2
3
4
5
6
7
# clone方法
我们来复制一个按钮
const button = GUI.Button.CreateImageButton('myBtn','点我!','vite.svg')
button.width = '200px'
button.height = '40px'
button.color = 'white'
button.background = 'deepskyblue'
button.onPointerUpObservable.add(function() {
planeMat.emissiveTexture = null
planeMat.emissiveColor = BABYLON.Color3.Teal()
})
advancedTexture.addControl(button)
const button2 = button.clone()
button2.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT
advancedTexture.addControl(button2)
2
3
4
5
6
7
8
9
10
11
12
13
14
但是按钮绑定的事件是不会被复制的,需要重新为复制的按钮绑定事件
# 如何定位控件
- 左中右水平对齐
button.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT
button.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_CENTER
button.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT
2
3
- 上中下垂直对齐
button2.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP
button2.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_CENTER
button2.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_BOTTOM
2
3
- 将控件设置在某个点
button.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT
button.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP
button.left = '100px'
button.top = '100px'
2
3
4
# 容器
const container = new GUI.Container()
container.background = 'black'
container.width = 0.5
container.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT
// 阻止container将事件传递到下层
container.isPointerBlocker = true
advancedTexture.addControl(container)
2
3
4
5
6
7
有几种类型的容器,其中一种是矩形,它是一个带边框的矩形
const rectangle = new GUI.Rectangle()
rectangle.width = '300px'
rectangle.height = '300px'
rectangle.cornerRadius = 50
rectangle.addControl(button2)
container.addControl(rectangle)
2
3
4
5
6
椭圆形容器
const ellipse = new GUI.Ellipse()
ellipse.width = '300px'
ellipse.height = '300px'
ellipse.thickness = 5
container.addControl(ellipse)
2
3
4
5
堆叠面板 它的特殊之处在于可以自动定位和组织子元素
const panel = new GUI.StackPanel()
const b1 = button.clone()
panel.addControl(b1)
const b2 = button.clone()
panel.addControl(b2)
const b3 = button.clone()
panel.addControl(b3)
advancedTexture.addControl(panel)
2
3
4
5
6
7
8
调试这些控件的css可以使用babylon的Inspector
Inspector.Show(scene, {})
# 让控件粘附在网格上
panel.linkWithMesh(plane)
panel.linkOffsetX = -500
panel.linkOffsetY = 100
2
3
# 让控件呈现网格的形状
const mesh = new BABYLON.MeshBuilder.CreatePlane('',{
width: 5,
height: 5
})
mesh.position.y = 2
mesh.rotation.y = Math.PI / 4
const advancedTexture2 = GUI.AdvancedDynamicTexture.CreateForMesh(mesh)
const picker = new GUI.ColorPicker()
picker.width = '500px'
advancedTexture2.addControl(picker)
2
3
4
5
6
7
8
9
10
11
12
const mesh = new BABYLON.MeshBuilder.CreateSphere('',{
diameter: 5
})
mesh.position.y = 2
const advancedTexture2 = GUI.AdvancedDynamicTexture.CreateForMesh(mesh)
const picker = new GUI.ColorPicker()
picker.width = '500px'
advancedTexture2.addControl(picker)
2
3
4
5
6
7
8
9
10
让控件始终面向摄像机
mesh.billboardMode = BABYLON.Mesh.BILLBOARDMODE_ALL
我们学会了如何用代码去创建GUI控件,并用Inspector去调试检查
# 图形化拖拽生成GUI
GUI Editor文档 (opens new window)
编辑完成后点击保存,获取json文件
const advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI('UI')
const loadedGUI = await advancedTexture.parseFromURLAsync('/guiTexture.json')
2
3
不过目前控件没有绑定事件,我们可以通过名字来获取到对应的控件
const text = advancedTexture.getControlByName('Textblock')
剩下的步骤就和前面学的一样了