UI 按钮事件
处理 UI 实体上的按钮事件。
要在你的 UI 中制作一个按钮,请创建一个 Button 具有以下属性的 UI 元素:
value:一个包含要显示在按钮上的文本的字符串。onMouseDown:一个回调函数,每当用户在实体上按下指针按钮时都会运行。uiTransform:UI 元素的定位属性。
下面的示例展示了如何创建一个可点击的 UI 按钮。
ui.tsx 文件:
import { Button } from '@dcl/sdk/react-ecs'
export const uiMenu = () => (
<Button
value="点击我"
uiTransform={{ width: 100, height: 100 }}
onMouseDown={() => {
console.log('点击了 UI')
}}
/>
)index.ts 文件:
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'
export function main() {
ReactEcsRenderer.setUiRenderer(uiMenu)
}你也可以把点击后执行的函数写在 UI 定义之外,并通过名称引用它。这有助于让 UI 代码更易读,如果有多个可点击的 UI 实体需要调用同一个函数,这也很有用。
以下字段可以添加到一个 Button UI 元素:
onMouseDown:一个回调函数,每当用户在实体上按下指针按钮时都会运行。onMouseUp:一个回调函数,每当指针在指向实体时松开按钮都会运行。onMouseEnter:一个回调函数,每当指针开始悬停在按钮上时都会运行。onMouseLeave:一个回调函数,每当指针停止悬停在按钮上时都会运行。color:按钮上文本的颜色。font:按钮上文本的字体。textAlign:按钮内部文本的对齐方式uiTransform:UI 元素的定位属性。uiBackground:设置 UI 元素的颜色或纹理。variant:使用此属性将按钮样式设置为默认样式之一。primary和secondary可用。disabled:用于将按钮设为禁用的布尔值。当disabled设置为 true时,onMouseDown和onMouseUp各项动作将不再被调用,按钮也不再响应任何指针交互。按钮还会被绘制成“灰掉”的状态:文本和背景的渲染透明度都只有原来的alpha值的一半。这里仅仅是显示上的变化。Color4中传入的值永远不会被修改,因此你可以安全地在多个元素之间复用一个共享调色板对象。
按钮样式
将 variant 设置为 primary 或 secondary ,即可利用按钮的默认样式选项。 primary 会让你的按钮变成红色白字, secondary 会让你的按钮变成白色红字。
你也可以自由使用背景上的所有属性。你还可以先设置一个 variant,然后覆盖其中的一些属性。此示例使用了 primary variant,但将颜色覆盖为绿色:
可切换按钮
一个常见的用法是让按钮在两种状态之间切换,就像一个开关。下面的示例在每次按下按钮时都会在两种颜色之间切换:
请注意,在上面的示例中,颜色取决于一个 buttonEnabled 变量。每当这个变量的值改变时,背景颜色会立即受到影响。
悬停反馈
另一个常见用法是在鼠标悬停在按钮上时显示某种视觉提示,以说明它是可交互的,甚至显示一个悬停提示来解释这个按钮的作用。使用 onMouseEnter 和 onMouseLeave 回调来检测玩家的光标何时位于按钮上,并做出相应反应。
使其他元素可点击
UI 中的任何元素都可以通过添加一个 onMouseDown 属性来变得可点击,它的工作方式与按钮完全相同。下面的示例为背景图像和文本添加了 onMouseDown 属性。
指针阻挡
默认情况下,所有 UI 实体都不会阻挡指针,这意味着玩家的点击会穿过它们,并与其后方 3D 世界空间中的对象交互。如果某个实体有一个 onMouseDown 回调,那么它就会变成指针阻挡,因此玩家的点击不会影响该 UI 实体后面的内容。
你可以通过更改 pointerFilter 属性在任何 UI 实体上的 uiTransform 组件值来改变这个默认行为。例如,要把一个没有 onMouseDown 的实体设为指针阻挡。
支持的 pointerFilter 值有:
block:该 UI 元素会阻挡指针,玩家无法点击这个 UI 元素后面的任何内容。none:该 UI 元素不会阻挡指针。该元素不可点击,其后方的任何内容都可以被点击。
下面是一个简单的 UI,它没有 onMouseDown,但通过设置 pointerFilter 为 block.
阻挡遵循布局框,而不是可见像素
一个阻挡元素会在其 整个矩形区域内捕获点击,无论那里是否绘制了任何内容。完全透明的背景不会产生任何影响。
把处理器附加到需要它们的最小元素上:面板、按钮、行。布局包装器应保持不带处理器。
有两种情况下,全屏阻挡元素是合适的,而且这两种情况都应是有意为之:
一个 模态遮罩层,用于吞掉点击,并且只在模态框打开时渲染。
一个 拖拽释放捕获器,它只在拖拽进行中存在。参见 拖拽交互 如下。
如果在你的场景中点击突然失效,首先检查这一点。
拖拽交互
UI 指针处理器(onMouseDown, onMouseUp, onMouseEnter, onMouseLeave)不接受参数。它们作为简单的 () => void 回调触发,不包含位置或坐标数据。UI 系统中没有 onMouseDrag 或 onMouseMove 处理器。
要构建基于拖拽的 UI(滑块、拖动条、拖拽手柄),请使用 PrimaryPointerInfo.screenDelta 来自 @dcl/sdk/ecs。这会给出自上一帧以来鼠标在像素上的移动量,并且无论光标位于何处都会每帧更新。
其模式如下:
onMouseDown在拖拽目标上开始拖拽并记录初始值。一个系统每帧读取
screenDelta,并在拖拽激活时将其累加到该值中。一个带有
pointerFilter: 'block'的全屏不可见覆盖层会捕获鼠标释放,因此即使在狭窄目标外松开,也仍然会结束拖拽。
最后更新于