欢迎光临
我们一直在努力

【Laya】TimeLine 使用说明

LayaAir TimeLine 使用说明

概述

TimeLine 类是 LayaAir 引擎中的时间轴动画类,用于创建复杂的动画序列。与 Tween 不同,TimeLine 可以管理多个动画标签(label),实现更精细的动画控制和序列编排。

目录

  • 基础用法
  • 链式调用 API
  • 标签系统
  • 播放控制
  • 完整示例

基础用法

创建 TimeLine

// 创建 TimeLine 实例
let timeLine = new Laya.TimeLine();

// 添加动画
timeLine.to(sprite, { x: 500 }, 1000);

// 播放
timeLine.play();

基本动画序列

let sprite = new Laya.Sprite();
sprite.graphics.drawRect(0, 0, 100, 100, "#FF0000");
sprite.pos(100, 100);
Laya.stage.addChild(sprite);

// 创建时间轴动画
let timeLine = new Laya.TimeLine();
timeLine.to(sprite, { x: 500 }, 1000, Laya.Ease.bounceOut);
timeLine.play();


链式调用 API

TimeLine 链式调用

TimeLine 支持链式调用,可以方便地构建复杂的动画序列。

let timeLine = new Laya.TimeLine();

// 链式添加多个动画
timeLine.to(sprite, { x: 500 }, 1000, Laya.Ease.bounceOut)
.to(sprite, { y: 300 }, 800, Laya.Ease.elasticOut)
.from(sprite, { scaleX: 0, scaleY: 0 }, 500, Laya.Ease.backOut)
.play();

链式方法说明

方法说明示例
to(target, props, duration, ease, delay) 从当前值动画到目标值 .to(sprite, {x: 500}, 1000)
from(target, props, duration, ease, delay) 从指定值动画到当前值 .from(sprite, {scaleX: 0}, 500)
addLabel(label, offset) 在指定时间位置添加标签 .addLabel("start", 0)
play(offset, loop) 播放时间轴 .play(0, false)
pause() 暂停播放 timeLine.pause()
resume() 恢复播放 timeLine.resume()
stop() 停止播放 timeLine.stop()
gotoLabel(label) 跳转到指定标签 .gotoLabel("start")
gotoTime(time) 跳转到指定时间(毫秒) .gotoTime(1000)
destroy() 销毁时间轴 timeLine.destroy()

属性

属性说明示例
scale 播放速度缩放,1.0 为正常速度 timeLine.scale = 2 (2倍速)
index 当前帧索引(可读写) timeLine.index
total 总帧数 timeLine.total

标签系统

标签是 TimeLine 的核心功能,允许在时间轴上标记关键位置。

添加和使用标签

let timeLine = new Laya.TimeLine();

// 在不同时间位置添加标签
timeLine.addLabel("start", 0) // 0ms 处添加 "start" 标签
.to(sprite, { x: 200 }, 500)
.addLabel("middle", 500) // 500ms 处添加 "middle" 标签
.to(sprite, { x: 400 }, 500)
.addLabel("end", 1000) // 1000ms 处添加 "end" 标签
.to(sprite, { x: 600 }, 500);

// 跳转到指定标签播放
timeLine.gotoLabel("middle");

// 或跳转到标签并播放
timeLine.play(0, false);
// 播放中可以跳转
timeLine.gotoLabel("start");

使用标签进行场景切换

// 创建一个带多个场景标签的动画
let timeLine = new Laya.TimeLine();

timeLine.addLabel("scene1", 0)
.to(sprite1, { alpha: 1 }, 500)
.addLabel("scene2", 500)
.to(sprite1, { alpha: 0 }, 500)
.to(sprite2, { alpha: 1 }, 500)
.addLabel("scene3", 1500)
.to(sprite2, { alpha: 0 }, 500)
.to(sprite3, { alpha: 1 }, 500);

// 按钮切换场景
button1.on(Laya.Event.CLICK, this, () => {
timeLine.gotoLabel("scene1");
});

button2.on(Laya.Event.CLICK, this, () => {
timeLine.gotoLabel("scene2");
});

button3.on(Laya.Event.CLICK, this, () => {
timeLine.gotoLabel("scene3");
});

timeLine.play(0, true); // 循环播放


播放控制

基本播放控制

let timeLine = new Laya.TimeLine();
timeLine.to(sprite, { x: 500 }, 2000);

// 播放
timeLine.play();

// 暂停
timeLine.pause();

// 恢复
timeLine.resume();

// 停止
timeLine.stop();

// 跳转到指定时间(毫秒)
timeLine.gotoTime(1000);

播放参数

// play(offset, loop)
// offset: 开始播放的时间偏移(毫秒)
// loop: 是否循环播放

// 从头开始播放,不循环
timeLine.play(0, false);

// 从 1 秒处开始播放
timeLine.play(1000, false);

// 循环播放
timeLine.play(0, true);

播放速度控制

// 设置播放速度
// 1.0 = 正常速度
// 2.0 = 2 倍速
// 0.5 = 0.5 倍速
timeLine.scale = 2;

// 实现慢动作效果
timeLine.scale = 0.5;

// 恢复正常速度
timeLine.scale = 1;


完整示例

示例1:基础动画序列

class BasicTimeLine {
private box: Laya.Sprite;
private timeLine: Laya.TimeLine;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBox();
this.createTimeLine();
});
}

private createBox(): void {
this.box = new Laya.Sprite();
this.box.graphics.drawRect(0, 0, 100, 100, "#FF7F50");
this.box.pivot(50, 50);
this.box.pos(100, 300);
Laya.stage.addChild(this.box);
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

// 创建三步动画序列
this.timeLine.to(this.box, { x: 300 }, 1000, Laya.Ease.cubicOut)
.to(this.box, { y: 150 }, 800, Laya.Ease.bounceOut)
.to(this.box, { rotation: 360 }, 1000, Laya.Ease.elasticOut);

// 播放
this.timeLine.play();
}
}

new BasicTimeLine();

示例2:多对象协同动画

class MultiObjectTimeLine {
private box1: Laya.Sprite;
private box2: Laya.Sprite;
private box3: Laya.Sprite;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBoxes();
this.createTimeLine();
});
}

private createBoxes(): void {
// 创建三个不同颜色的方块
this.box1 = new Laya.Sprite();
this.box1.graphics.drawRect(0, 0, 80, 80, "#FF5722");
this.box1.pos(100, 300);
Laya.stage.addChild(this.box1);

this.box2 = new Laya.Sprite();
this.box2.graphics.drawRect(0, 0, 80, 80, "#4CAF50");
this.box2.pos(100, 400);
Laya.stage.addChild(this.box2);

this.box3 = new Laya.Sprite();
this.box3.graphics.drawRect(0, 0, 80, 80, "#2196F3");
this.box3.pos(100, 500);
Laya.stage.addChild(this.box3);
}

private createTimeLine(): void {
let timeLine = new Laya.TimeLine();

// 三个对象依次进入
timeLine.to(this.box1, { x: 400 }, 600, Laya.Ease.backOut)
.to(this.box2, { x: 400 }, 600, Laya.Ease.backOut, 100) // 延迟 100ms
.to(this.box3, { x: 400 }, 600, Laya.Ease.backOut, 200); // 延迟 200ms

timeLine.play();
}
}

new MultiObjectTimeLine();

示例3:使用标签的场景切换

class LabelTimeLine {
private sprite: Laya.Sprite;
private timeLine: Laya.TimeLine;
private buttons: Laya.Sprite[] = [];

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createSprite();
this.createButtons();
this.createTimeLine();
});
}

private createSprite(): void {
this.sprite = new Laya.Sprite();
this.sprite.graphics.drawCircle(0, 0, 50, "#E91E63");
this.sprite.pos(150, 300);
Laya.stage.addChild(this.sprite);
}

private createButtons(): void {
let labels = ["位置A", "位置B", "位置C"];
let colors = ["#FF5722", "#4CAF50", "#2196F3"];

for (let i = 0; i < 3; i++) {
let btn = new Laya.Sprite();
btn.graphics.drawRect(0, 0, 100, 40, colors[i]);
btn.size(100, 40); // 设置点击区域
btn.pos(100 + i * 150, 500);
Laya.stage.addChild(btn);
this.buttons.push(btn);

btn.on(Laya.Event.CLICK, this, () => {
this.timeLine.gotoLabel(labels[i]);
});

let text = new Laya.Text();
text.text = labels[i];
text.color = "#FFFFFF";
text.fontSize = 16;
text.pos(100 + i * 150 + 25, 508);
Laya.stage.addChild(text);
}
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

// 定义三个位置的动画
this.timeLine.addLabel("位置A", 0)
.to(this.sprite, { x: 150, y: 300 }, 800, Laya.Ease.bounceOut)
.addLabel("位置B", 800)
.to(this.sprite, { x: 400, y: 300 }, 800, Laya.Ease.bounceOut)
.addLabel("位置C", 1600)
.to(this.sprite, { x: 650, y: 300 }, 800, Laya.Ease.bounceOut);

this.timeLine.play(0, true); // 循环播放
}
}

new LabelTimeLine();

示例4:暂停与恢复控制

class PauseResumeTimeLine {
private box: Laya.Sprite;
private timeLine: Laya.TimeLine;
private isPaused: boolean = false;
private statusText: Laya.Text;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBox();
this.createUI();
this.createTimeLine();
});
}

private createBox(): void {
this.box = new Laya.Sprite();
this.box.graphics.drawRect(0, 0, 100, 100, "#9C27B0");
this.box.pivot(50, 50);
this.box.pos(100, 300);
Laya.stage.addChild(this.box);
}

private createUI(): void {
// 状态文字
this.statusText = new Laya.Text();
this.statusText.text = "点击舞台暂停/恢复";
this.statusText.color = "#FFFFFF";
this.statusText.fontSize = 24;
this.statusText.pos(250, 500);
Laya.stage.addChild(this.statusText);
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

// 创建一个较长的动画
this.timeLine.to(this.box, { x: 700 }, 3000, Laya.Ease.linearNone)
.to(this.box, { rotation: 360 }, 2000);

this.timeLine.play(0, true);

// 点击舞台暂停/恢复
Laya.stage.on(Laya.Event.CLICK, this, this.togglePause);
}

private togglePause(): void {
if (this.isPaused) {
this.timeLine.resume();
this.statusText.text = "点击舞台暂停/恢复";
this.isPaused = false;
} else {
this.timeLine.pause();
this.statusText.text = "已暂停 – 点击恢复";
this.isPaused = true;
}
}
}

new PauseResumeTimeLine();

示例5:变速播放

class SpeedControlTimeLine {
private box: Laya.Sprite;
private timeLine: Laya.TimeLine;
private currentSpeed: number = 1;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBox();
this.createUI();
this.createTimeLine();
});
}

private createBox(): void {
this.box = new Laya.Sprite();
this.box.graphics.drawRect(0, 0, 100, 100, "#FF9800");
this.box.pivot(50, 50);
this.box.pos(100, 300);
Laya.stage.addChild(this.box);
}

private createUI(): void {
let buttons = [
{ label: "0.5x", speed: 0.5, x: 100 },
{ label: "1x", speed: 1, x: 250 },
{ label: "2x", speed: 2, x: 400 },
{ label: "3x", speed: 3, x: 550 }
];

buttons.forEach(btn => {
let sprite = new Laya.Sprite();
sprite.graphics.drawRect(0, 0, 80, 40, "#424242");
sprite.size(80, 40); // 设置点击区域
sprite.pos(btn.x, 500);
Laya.stage.addChild(sprite);

let text = new Laya.Text();
text.text = btn.label;
text.color = "#FFFFFF";
text.fontSize = 18;
text.pos(btn.x + 25, 508);
Laya.stage.addChild(text);

sprite.on(Laya.Event.CLICK, this, () => {
this.timeLine.scale = btn.speed;
this.currentSpeed = btn.speed;
console.log("播放速度:", btn.speed);
});
});
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

this.timeLine.to(this.box, { x: 700 }, 2000, Laya.Ease.cubicInOut)
.to(this.box, { x: 100 }, 2000, Laya.Ease.cubicInOut);

this.timeLine.play(0, true);
}
}

new SpeedControlTimeLine();

示例6:组合动画(位置+旋转+缩放)

class ComboTimeLine {
private box: Laya.Sprite;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBox();
this.createTimeLine();
});
}

private createBox(): void {
this.box = new Laya.Sprite();
this.box.graphics.drawRect(0, 0, 100, 100, "#00BCD4");
this.box.pivot(50, 50);
this.box.pos(100, 300);
Laya.stage.addChild(this.box);

// 点击重新播放
Laya.stage.on(Laya.Event.CLICK, this, () => {
this.createTimeLine();
});
}

private createTimeLine(): void {
let timeLine = new Laya.TimeLine();

// 复杂的组合动画
timeLine.to(this.box, { x: 400, y: 300, scaleX: 1.5, scaleY: 1.5, rotation: 180 },
1500, Laya.Ease.elasticOut)
.to(this.box, { x: 700, y: 150, scaleX: 1, scaleY: 1, rotation: 360 },
1200, Laya.Ease.bounceOut)
.to(this.box, { alpha: 0 }, 500, Laya.Ease.linearNone);

timeLine.play();
}
}

new ComboTimeLine();

示例7:循环动画效果

class LoopTimeLine {
constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createLoadingAnimation();
});
}

private createLoadingAnimation(): void {
let dots: Laya.Sprite[] = [];

// 创建多个点
for (let i = 0; i < 5; i++) {
let dot = new Laya.Sprite();
dot.graphics.drawCircle(0, 0, 15, "#FF4081");
dot.pos(250 + i * 80, 300);
Laya.stage.addChild(dot);
dots.push(dot);
}

let timeLine = new Laya.TimeLine();

// 波浪式动画
dots.forEach((dot, index) => {
timeLine.to(dot, { y: 200 }, 400, Laya.Ease.sineOut, index * 80)
.to(dot, { y: 300 }, 400, Laya.Ease.sineIn);
});

// 循环播放
timeLine.play(0, true);
}
}

new LoopTimeLine();

示例8:淡入淡出切换效果

class FadeTimeLine {
private sprite1: Laya.Sprite;
private sprite2: Laya.Sprite;
private timeLine: Laya.TimeLine;

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createSprites();
this.createTimeLine();
});
}

private createSprites(): void {
// 第一个精灵(红色)
this.sprite1 = new Laya.Sprite();
this.sprite1.graphics.drawRect(0, 0, 200, 200, "#F44336");
this.sprite1.pos(300, 200);
this.sprite1.alpha = 1;
Laya.stage.addChild(this.sprite1);

// 第二个精灵(蓝色)
this.sprite2 = new Laya.Sprite();
this.sprite2.graphics.drawRect(0, 0, 200, 200, "#2196F3");
this.sprite2.pos(300, 200);
this.sprite2.alpha = 0;
Laya.stage.addChild(this.sprite2);

// 点击切换
Laya.stage.on(Laya.Event.CLICK, this, () => {
this.timeLine.play(0, false);
});
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

// 淡出 sprite1,淡入 sprite2
this.timeLine.to(this.sprite1, { alpha: 0 }, 800, Laya.Ease.linearNone)
.to(this.sprite2, { alpha: 1 }, 800, Laya.Ease.linearNone);

this.timeLine.play(0, true); // 循环播放
}
}

new FadeTimeLine();

示例9:使用 gotoTime 精确控制

class GotoTimeTimeLine {
private box: Laya.Sprite;
private timeLine: Laya.TimeLine;
private totalTime: number = 5000; // 总时长(毫秒),需手动计算

constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createBox();
this.createProgressBar();
this.createTimeLine();
});
}

private createBox(): void {
this.box = new Laya.Sprite();
this.box.graphics.drawRect(0, 0, 100, 100, "#8BC34A");
this.box.pivot(50, 50);
this.box.pos(100, 250);
Laya.stage.addChild(this.box);
}

private createProgressBar(): void {
// 进度条背景
let bg = new Laya.Sprite();
bg.graphics.drawRect(0, 0, 600, 10, "#424242");
bg.pos(100, 450);
Laya.stage.addChild(bg);

// 创建可点击的进度条
let progressBar = new Laya.Sprite();
progressBar.graphics.drawRect(0, 0, 600, 30, "#000000"); // 透明点击区域
progressBar.size(600, 30); // 设置点击区域
progressBar.pos(100, 440);
progressBar.alpha = 0.01;
Laya.stage.addChild(progressBar);

progressBar.on(Laya.Event.CLICK, this, (e: Laya.Event) => {
// 计算点击位置对应的进度时间
let clickX = e.stageX – 100;
let progress = clickX / 600;
let targetTime = progress * this.totalTime;

this.timeLine.gotoTime(targetTime);
console.log("跳转到时间:", targetTime, "ms");
});

// 添加提示文字
let text = new Laya.Text();
text.text = "点击进度条跳转";
text.color = "#AAAAAA";
text.fontSize = 16;
text.pos(320, 480);
Laya.stage.addChild(text);
}

private createTimeLine(): void {
this.timeLine = new Laya.TimeLine();

// 创建一个可预览进度的动画
this.timeLine.to(this.box, { x: 700 }, 3000, Laya.Ease.cubicInOut)
.to(this.box, { rotation: 360 }, 2000, Laya.Ease.linearNone);

this.timeLine.play(0, true);
}
}

new GotoTimeTimeLine();

示例10:复杂的过场动画

class TransitionTimeLine {
constructor() {
Laya.init(800, 600).then(() => {
Laya.stage.bgColor = "#232628";
this.createTransition();
});
}

private createTransition(): void {
// 创建标题文字
let title = new Laya.Text();
title.text = "GAME OVER";
title.color = "#FFFFFF";
title.fontSize = 80;
title.bold = true;
title.pos(400, 300);
title.alpha = 0;
title.pivot(title.width / 2, title.height / 2);
Laya.stage.addChild(title);

// 创建背景遮罩
let overlay = new Laya.Sprite();
overlay.graphics.drawRect(0, 0, 800, 600, "#000000");
overlay.alpha = 0;
Laya.stage.addChild(overlay);

// 创建按钮
let button = new Laya.Sprite();
button.graphics.drawRect(0, 0, 200, 60, "#FF5722");
button.pos(300, 400);
button.scaleY = 0;
Laya.stage.addChild(button);

let buttonText = new Laya.Text();
buttonText.text = "RETRY";
buttonText.color = "#FFFFFF";
buttonText.fontSize = 30;
buttonText.pos(360, 415);
buttonText.alpha = 0;
Laya.stage.addChild(buttonText);

// 创建过场动画时间轴
let timeLine = new Laya.TimeLine();

timeLine.addLabel("fade_in", 0)
// 背景渐显
.to(overlay, { alpha: 0.7 }, 500, Laya.Ease.linearNone)
// 标题弹入
.addLabel("title_in", 500)
.to(title, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, 800, Laya.Ease.backOut)
.to(title, { scaleX: 1, scaleY: 1 }, 300, Laya.Ease.linearNone)
// 按钮出现
.addLabel("button_in", 1600)
.to(button, { scaleY: 1 }, 500, Laya.Ease.backOut)
.to(buttonText, { alpha: 1 }, 300, Laya.Ease.linearNone);

timeLine.play(0, false);
}
}

new TransitionTimeLine();


TimeLine 与 Tween 的对比

特性TimeLineTween
适用场景 复杂的动画序列编排 单个或简单动画
标签系统 支持(可添加多个标签) 不支持
多对象动画 支持统一管理多个对象 每个对象独立控制
播放控制 play/pause/resume/stop/goto pause/resume/kill
速度控制 scale 属性 timeScale 方法
循环控制 play(loop) repeat(count)
链式调用 to/from/addLabel to/from/go/duration 等

注意事项

  • 内存管理:不再使用时调用 destroy() 方法销毁 TimeLine 实例

  • 避免重复播放:在调用 play() 前先调用 stop() 或 destroy()

  • 标签命名:使用有意义的标签名称,便于维护

  • 性能优化:大量动画时考虑对象池,避免频繁创建销毁 TimeLine

  • 时间单位:TimeLine 中所有时间单位均为毫秒(ms)

  • 目标对象引用:确保动画期间目标对象不被销毁

  • 与 Tween 配合:TimeLine 适合编排复杂序列,Tween 适合简单单一动画

  • 按钮点击区域:使用 drawRect 创建按钮时,必须调用 size(width, height) 设置点击区域,否则无法触发事件

    let btn = new Laya.Sprite();
    btn.graphics.drawRect(0, 0, 100, 40, "#FF0000");
    btn.size(100, 40); // 必须设置,否则无法触发点击事件

  • 赞(0)
    未经允许不得转载:171主机测评 » 【Laya】TimeLine 使用说明
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址