【Laya】Button 拓展方法
本文介绍了Laya引擎中按钮组件的三种扩展方法对比及实现方式。方式一通过ButtonHelper类提供运行时动态配置,支持多种预设动画效果和自定义逻辑;方式二采用类似Unity的组件化设计,可在IDE面板可视化配置;方式三则通过IDE面板直接注册事件实现简单交互。文章详细说明了每种方式的适用场景、优缺点,并提供了代码示例和API参考,帮助开发者根据项目需求选择最佳实践方案。
Laya Button 拓展方法
目录
三种使用方式对比
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| ButtonHelper | 代码动态创建按钮 | 灵活,运行时配置 | 需要编写代码 |
| ButtonAnimComponent | Unity 风格,IDE 配置 | 可视化配置,设计友好 | 需要添加组件 |
| IDE 面板注册 | 快速原型,简单交互 | 最简单,非零代码 | 仅支持简单逻辑 |
方式一:ButtonHelper 拓展方式
ButtonHelper 是按钮辅助类,为按钮提供统一的点击音效和动画效果。
特点
- ✅ 运行时动态配置
- ✅ 支持多种预设动画
- ✅ 可自定义动画逻辑
- ✅ 统一的音效管理
动画类型
| 类型 | 效果描述 |
|---|---|
ButtonAnimType.None |
无动画 |
ButtonAnimType.Scale |
缩放动画:按下缩小后弹回 |
ButtonAnimType.Shake |
摇晃动画:左右摇晃后回正 |
ButtonAnimType.Bounce |
弹跳动画:压扁后回弹 |
ButtonAnimType.Rotate |
旋转动画:旋转一定角度 |
ButtonAnimType.Pulse |
脉冲动画:放大后弹回 |
ButtonAnimType.Custom |
自定义动画 |
基础用法
import { ButtonHelper, ButtonAnimType } from "./button/utils/ButtonHelper";
// 1. 简单使用 - 指定动画类型
ButtonHelper.setupButton(btnConfirm, ButtonAnimType.Scale);
ButtonHelper.setupButton(btnCancel, ButtonAnimType.Shake);
// 2. 使用预设配置
import { ButtonAnimPresets } from "./button/utils/ButtonHelper";
ButtonHelper.setupButton(btnOK, ButtonAnimPresets.Primary);
ButtonHelper.setupButton(btnDelete, ButtonAnimPresets.Danger);
完整配置示例
ButtonHelper.setupButton(btnAttack, {
type: ButtonAnimType.Rotate,
sound: "resources/audio/click.mp3", // 音效路径
soundVolume: 0.8, // 音量 0-1
rotation: 180, // 旋转角度
duration: 200, // 动画时长(ms)
ease: Laya.Ease.backOut, // 缓动函数
onComplete: () => { // 动画完成回调
console.log("动画完成");
}
});
自定义动画示例
ButtonHelper.setupButton(btnSpecial, {
type: ButtonAnimType.Custom,
sound: "resources/audio/special.mp3",
customAnim: (btn: Laya.Button) => {
Laya.TimeLine.to(btn, { rotation: 720, scaleX: 0, scaleY: 0 }, 300)
.to(btn, { rotation: 0, scaleX: 1, scaleY: 1 }, 400, Laya.Ease.elasticOut)
.play();
}
});
预设配置
import { ButtonAnimPresets } from "./button/utils/ButtonHelper";
ButtonAnimPresets.Primary // 主要按钮:缩放 + 默认点击音
ButtonAnimPresets.Danger // 危险按钮:摇晃 + 取消音
ButtonAnimPresets.Success // 成功按钮:脉冲 + 确认音
ButtonAnimPresets.Attack // 攻击按钮:旋转 + 攻击音
完整示例:StartScript.ts
import { ButtonHelper, ButtonAnimType } from "../index";
const {regClass, property} = Laya;
@regClass()
export class StartScript extends Laya.Script {
/** 按钮引用(在 IDE 中拖拽赋值) */
@property(Laya.Button)
public button: Laya.Button;
onEnable(): void {
// 设置全局音量
Laya.SoundManager.soundVolume = 0.2;
// 配置按钮动画和音效
ButtonHelper.setupButton(this.button, {
type: ButtonAnimType.Bounce,
sound: "resources/audio/click.mp3",
duration: 100,
onComplete: () => {
// 动画完成后打开游戏场景
Laya.Scene.open("Game.ls");
}
});
}
onDisable(): void {
// 清理资源
Laya.SoundManager.stopAllSound();
ButtonHelper.cleanup(this.button);
}
}
创建测试按钮示例
import { ButtonHelper, ButtonAnimType, ButtonAnimPresets } from "./button/utils/ButtonHelper";
function createTestButton(label: string, x: number, y: number): Laya.Button {
const btn = new Laya.Button();
btn.skin = "atlas/comp/button.png";
btn.label = label;
btn.labelSize = 24;
btn.labelColors = "#ffffff,#d4d4d4,#8a8a8a";
btn.size(160, 50);
btn.pos(x, y);
Laya.stage.addChild(btn);
return btn;
}
// 创建测试按钮
const btnConfirm = createTestButton("缩放动画", 100, 100);
const btnCancel = createTestButton("摇晃动画", 300, 100);
const btnOK = createTestButton("Primary预设", 100, 180);
const btnAttack = createTestButton("旋转攻击", 100, 260);
// 1. 简单使用 - 预设动画类型
ButtonHelper.setupButton(btnConfirm, ButtonAnimType.Scale);
ButtonHelper.setupButton(btnCancel, ButtonAnimType.Shake);
// 2. 使用预设配置
ButtonHelper.setupButton(btnOK, ButtonAnimPresets.Primary);
// 3. 自定义配置(带音效)
ButtonHelper.setupButton(btnAttack, {
type: ButtonAnimType.Rotate,
sound: "resources/audio/click.mp3",
soundVolume: 0.8,
rotation: 180,
duration: 200
});
// 添加点击事件
btnConfirm.clickHandler = Laya.Handler.create(null, () => console.log("点击了确认"));
方式二:ButtonAnimComponent 组件方式
类似 Unity 的组件化设计,通过添加组件到按钮上,在 IDE 面板中配置动画和事件。
特点
- ✅ Unity 风格的组件设计
- ✅ IDE 可视化配置
- ✅ 支持方法名绑定(字符串类型。若喜欢无代码编程可使用GUI)
组件属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
animType |
ButtonAnimType | Scale | 动画类型 |
sound |
String | “” | 点击音效路径 |
soundVolume |
Number | 1 | 音效音量 (0-1) |
duration |
Number | 100 | 动画持续时间(ms) |
scale |
Number | 0.9 | 缩放比例 |
rotation |
Number | 15 | 旋转角度 |
onClickMethodName |
String | “” | 点击事件方法名 |
使用步骤
1. 在 IDE 中添加组件
- 选中场景中的 Button 节点
- 在属性检查器中点击"添加组件"
- 选择
ButtonAnimComponent - 在面板中配置动画参数
2. 配置点击事件
工作原理:
onClickMethodName 使用字符串反射机制,在运行时动态查找和调用方法。查找顺序如下:
1. 在 owner 节点的所有 Script 组件中查找
↓ 找到则调用并停止
2. 在 owner 节点自身查找
↓ 找到则调用并停止
3. 未找到则输出警告
查找机制详解:
// ButtonAnimComponent 内部实现
private invokeMethodByName(methodName: string): void {
if (!this.owner) return;
// 1️⃣ 在 owner 的所有 Script 组件中查找
const scripts = this.owner.getComponents(Laya.Script);
for (const script of scripts) {
const method = (script as any)[methodName];
if (method && typeof method === 'function') {
method.call(script); // 找到!调用并停止
return;
}
}
// 2️⃣ 如果 Script 中没找到,在 owner 自身上查找
const ownerMethod = (this.owner as any)[methodName];
if (ownerMethod && typeof ownerMethod === 'function') {
ownerMethod.call(this.owner); // 找到!调用并停止
return;
}
// 3️⃣ 未找到,输出警告
console.warn(`[ButtonAnimComponent] 未找到方法: ${methodName}`);
}
方式一:通过方法名绑定(推荐)
在脚本中定义方法:
const {regClass} = Laya;
@regClass()
export class ClickScript extends Laya.Script {
onClick(): void {
console.log("点击了按钮");
}
}
然后在 IDE 中:
- 将
ClickScript脚本添加到按钮节点(或其父节点) - 在
ButtonAnimComponent的onClickMethodName属性中输入onClick
查找示例:
// 场景结构
Button (Button)
├── ButtonAnimComponent (onClickMethodName = "handleClick")
└── ClickScript (Script)
└── handleClick() // ✅ 在这里找到并调用
多组件场景:
// 场景结构
Button (Button)
├── ButtonAnimComponent (onClickMethodName = "onMenuClick")
├── MenuScript (Script)
│ └── onMenuClick() // ✅ 优先在 Script 组件中查找
└── AnotherScript (Script)
└── onMenuClick() // ✅ 找到第一个后停止
// 查找顺序:MenuScript → AnotherScript
在 owner 自身上定义方法:
const {regClass} = Laya;
@regClass()
export class CustomButton extends Laya.Button {
// 在 Button 自身上定义方法
onButtonClick(): void {
console.log("按钮被点击,方法在 owner 自身上");
}
}
// 场景结构
CustomButton (继承自 Button)
├── ButtonAnimComponent (onClickMethodName = "onButtonClick")
└── (没有 Script 组件)
// 查找顺序:
// 1. Script 组件:❌ 未找到
// 2. owner 自身:✅ 在 CustomButton 上找到并调用
方法名冲突处理:
// ⚠️ 如果多个 Script 组件有同名方法
Button (Button)
├── ButtonAnimComponent (onClickMethodName = "handleClick")
├── MenuScript (Script)
│ └── handleClick() // ✅ 第一个找到的被调用
└── AnotherScript (Script)
└── handleClick() // ❌ 不会被调用
// 解决方案:使用不同的方法名
onClickMethodName = "onMenuClick" // MenuScript.handleMenuClick
onClickMethodName = "onItemClick" // AnotherScript.handleItemClick
参数传递限制:
// ❌ 不支持:方法不能有参数
handleClick(event: Laya.Event): void {
// onClickMethodName 不支持参数传递
}
// ✅ 正确:方法必须无参数
handleClick(): void {
// 可以通过 this.owner 访问节点
const btn = this.owner as Laya.Button;
console.log("按钮标签:", btn.label);
}
完整示例:游戏 UI 菜单:
const {regClass} = Laya;
@regClass()
export class MenuScript extends Laya.Script {
/** 开始按钮 */
@property(Laya.Button)
public startButton: Laya.Button;
/** 设置按钮 */
@property(Laya.Button)
public settingsButton: Laya.Button;
/** 退出按钮 */
@property(Laya.Button)
public quitButton: Laya.Button;
onEnable(): void {
// 可以在代码中额外配置
this.startButton.label = "开始游戏";
this.settingsButton.label = "设置";
this.quitButton.label = "退出";
}
/** 开始游戏 */
onStartClick(): void {
console.log("开始游戏");
Laya.Scene.open("Game.ls");
}
/** 打开设置 */
onSettingsClick(): void {
console.log("打开设置");
Laya.Scene.open("Settings.ls");
}
/** 退出游戏 */
onQuitClick(): void {
console.log("退出游戏");
Laya.Browser.close();
}
}
IDE 配置:
场景结构:
Scene
├── StartButton (Button)
│ ├── ButtonAnimComponent (onClickMethodName: "onStartClick")
│ └── MenuScript (Script)
├── SettingsButton (Button)
│ ├── ButtonAnimComponent (onClickMethodName: "onSettingsClick")
│ └── MenuScript (Script)
└── QuitButton (Button)
├── ButtonAnimComponent (onClickMethodName: "onQuitClick")
└── MenuScript (Script)
方式二:代码中动态设置
const {regClass} = Laya;
@regClass()
export class GameScript extends Laya.Script {
@property({type: Laya.Button})
public startButton: Laya.Button;
onEnable(): void {
// 获取按钮上的组件
const animComp = this.startButton.getComponent(ButtonAnimComponent);
// 设置点击回调(代码方式,支持闭包)
animComp.onClick = Laya.Handler.create(this, () => {
this.startGame();
});
}
startGame(): void {
console.log("开始游戏");
Laya.Scene.open("Game.ls");
}
}
完整示例:ClickScript.ts
脚本定义:
const {regClass} = Laya;
@regClass()
export class ClickScript extends Laya.Script {
onClick(): void {
console.log("点击了按钮");
// 可以访问 owner 获取节点信息
console.log("按钮名称:", this.owner.name);
// 可以获取组件上的其他组件
const btn = this.owner as Laya.Button;
console.log("按钮标签:", btn.label);
}
}
IDE 配置步骤:
- 在场景层级中选中 Button 节点
- 添加
ButtonAnimComponent组件 - 配置动画参数:
animType: Scalesound: resources/audio/click.mp3duration: 100
- 添加
ClickScript脚本到同一节点(或父节点) - 在
ButtonAnimComponent的onClickMethodName中输入onClick
高级用法:运行时配置
const {regClass} = Laya;
@regClass()
export class DynamicButtonScript extends Laya.Script {
onEnable(): void {
const button = this.owner as Laya.Button;
// 获取或添加动画组件
let animComp = button.getComponent(ButtonAnimComponent);
if (!animComp) {
animComp = button.addComponent(ButtonAnimComponent);
}
// 应用配置
animComp.applyConfig({
type: ButtonAnimType.Rotate,
sound: "resources/audio/click.mp3",
soundVolume: 0.8,
duration: 200,
rotation: 360
});
// 设置点击回调
animComp.onClick = Laya.Handler.create(this, () => {
this.onButtonClick();
});
}
onButtonClick(): void {
console.log("按钮被点击");
// 手动触发动画
const animComp = (this.owner as Laya.Button).getComponent(ButtonAnimComponent);
animComp.triggerAnimation();
}
}
组件清理
组件会自动管理生命周期,无需手动清理:
onDisable(): void {
// 组件自动清理动画和事件监听
}
方式三:IDE 面板注册事件
最简单的方式,直接在 IDE 面板中注册按钮点击事件。
特点
- ✅ 零代码配置
- ✅ 快速原型开发
- ✅ 设计师友好
- ⚠️ 仅支持简单逻辑
使用步骤
1. 创建脚本方法
const {regClass} = Laya;
@regClass()
export class MainScript extends Laya.Script {
/** 按钮引用 */
@property(Laya.Button)
public startButton: Laya.Button;
onEnable(): void {
// 可以在这里进行额外初始化
}
/** 开始游戏方法 */
onGameStart(): void {
console.log("开始游戏");
Laya.Scene.open("Game.ls");
}
/** 打开设置方法 */
onOpenSettings(): void {
console.log("打开设置");
Laya.Scene.open("Settings.ls");
}
}
2. 在 IDE 中绑定事件
- 选中场景中的 Button 节点
- 在属性检查器中找到"组件"列表
- 找到
Button组件的事件部分 - 点击
click事件旁边的+按钮 - 选择节点和脚本方法(如
MainScript.onGameStart)
图示说明:
┌─────────────────────────────┐
│ Button 组件属性 │
├─────────────────────────────┤
│ skin: button.png │
│ label: 开始游戏 │
│ stateNum: 3 │
├─────────────────────────────┤
│ 事件 │
├─────────────────────────────┤
│ click: [+] │
│ └─ MainScript.onGameStart │
└─────────────────────────────┘
完整示例
场景结构:
Scene
├── StartButton (Button)
│ └── MainScript (Script)
└── SettingsButton (Button)
└── MainScript (Script)
脚本代码:
const {regClass, property} = Laya;
@regClass()
export class MainScript extends Laya.Script {
/** 开始按钮 */
@property(Laya.Button)
public startButton: Laya.Button;
/** 设置按钮 */
@property(Laya.Button)
public settingsButton: Laya.Button;
onEnable(): void {
// 可选:在代码中设置按钮属性
this.startButton.labelSize = 24;
this.startButton.labelColors = "#ffffff,#ffff00,#cccccc";
}
/** 开始游戏 */
onGameStart(): void {
console.log("开始游戏");
Laya.Scene.open("Game.ls");
}
/** 打开设置 */
onOpenSettings(): void {
console.log("打开设置");
Laya.Scene.open("Settings.ls");
}
}
IDE 配置:
- 选中
StartButton节点 - 在 Button 组件的
事件→click中,选择MainScript.onGameStart - 选中
SettingsButton节点 - 在 Button 组件的
事件→click中,选择MainScript.onOpenSettings
优缺点
优点:
- 最简单,无需编写事件绑定代码
- 可视化配置,一目了然
- 适合快速原型
缺点:
- 只能绑定一个方法
- 不支持传递参数
- 复杂逻辑需要额外处理
API 参考
ButtonHelper.setupButton()
static setupButton(
button: Laya.Button,
config: ButtonAnimConfig | ButtonAnimType
): void
配置按钮的点击动画和音效效果。
参数:
button- 按钮实例config- 动画配置对象或动画类型枚举
ButtonAnimConfig
interface ButtonAnimConfig {
type: ButtonAnimType; // 动画类型
sound?: string; // 音效路径
soundVolume?: number; // 音量 (0-1)
duration?: number; // 动画时长(ms)
scale?: number; // 缩放比例
rotation?: number; // 旋转角度
ease?: Function; // 缓动函数
customAnim?: (target: Laya.Button) => void; // 自定义动画
onComplete?: () => void; // 动画完成回调
}
ButtonAnimComponent 主要方法
| 方法 | 说明 |
|---|---|
applyConfig(config) |
从配置对象快速设置属性 |
triggerAnimation() |
手动触发动画 |
最佳实践
1. 选择合适的使用方式
| 场景 | 推荐方式 |
|---|---|
| 运行时动态创建按钮 | ButtonHelper |
| Unity 背景,习惯组件化 | ButtonAnimComponent |
| 快速原型,简单交互 | IDE 面板注册 |
2. 事件监听对比
| 方式 | 优点 | 缺点 |
|---|---|---|
clickHandler |
Button 内置,自动清理 | 只能设置一个处理器 |
on(Event.CLICK) |
支持多个监听器,更灵活 | 需要手动管理清理 |
推荐:
- 简单按钮使用
clickHandler - 需要多个监听器时使用
on(Event.CLICK)
3. 动画系统使用
LayaAir 中链式动画的正确用法:
// ❌ 错误 - Tween.to 不支持链式调用
Laya.Tween.to(btn, { scaleX: 0.9 }, 50)
.to(btn, { scaleX: 1 }, 100);
// ✅ 正确 - 使用 TimeLine
Laya.TimeLine.to(btn, { scaleX: 0.9 }, 50)
.to(btn, { scaleX: 1 }, 100, Laya.Ease.elasticOut)
.play();
4. 内存管理
- 按钮销毁时,事件监听器会自动清理
ButtonHelper内部使用WeakSet跟踪按钮,不会造成内存泄漏ButtonAnimComponent会在onDisable时自动清理动画
5. 性能优化
// ✅ 推荐:使用对象池复用按钮
let button = Laya.Pool.getItemByClass("Button", Laya.Button);
button.skin = "atlas/comp/button.png";
// ✅ 推荐:避免在 onUpdate 中频繁操作按钮
onUpdate(): void {
// ❌ 避免
this.button.alpha = Math.sin(Laya.timer.now * 0.001);
}
6. 组件设计原则
ButtonAnimComponent 设计参考:
@regClass()
export class ButtonAnimComponent extends Laya.Component {
// 1. 使用 @property 暴露可配置属性
@property({type: ButtonAnimType})
animType: ButtonAnimType = ButtonAnimType.Scale;
@property({type: String, isAsset: true, assetTypeFilter: "Audio"})
sound: string = "";
// 2. 在生命周期中管理资源
onEnable(): void {
// 初始化
}
onDisable(): void {
// 清理资源
this.clearAllAnimations();
}
// 3. 提供公共方法供外部调用
public applyConfig(config: ButtonAnimConfig): void {
// 批量设置属性
}
public triggerAnimation(): void {
// 手动触发动画
}
}
注意事项
事件监听
// ✅ 推荐:使用 clickHandler
btn.clickHandler = Laya.Handler.create(this, () => {
console.log("按钮被点击");
});
// ✅ 也可以:使用事件监听
btn.on(Laya.Event.CLICK, this, () => {
console.log("按钮被点击");
});
文本颜色设置
// 格式:"弹起色,经过色,按下色"
btn.labelColors = "#ffffff,#ffff00,#cccccc";
btn.labelStroke = 2;
btn.labelStrokeColor = "#000000";
Toggle 按钮
const toggleBtn = new Laya.Button();
toggleBtn.toggle = true;
toggleBtn.on(Laya.Event.CLICK, toggleBtn, () => {
console.log("选中状态:", toggleBtn.selected);
});
状态切换
// 两态按钮
const btn2 = new Laya.Button();
btn2.stateNum = 2;
btn2.skin = "resources/two_state.png";
// 单态按钮
const btn1 = new Laya.Button();
btn1.stateNum = 1;
btn1.skin = "resources/one_state.png";
相关文档
这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!
更多推荐


所有评论(0)