经典UI Sprite介绍

一、概述

Sprite(精灵)是 LayaAir 引擎中基本的显示图形的显示列表节点。它是2D游戏开发中最核心的显示对象类,所有2D UI节点对象都继承自 Sprite 类。

主要特性

  • 显示图形:通过 graphics 可以绘制图片或者矢量图
  • 变换操作:支持旋转、缩放、位移、倾斜等操作
  • 容器功能:可作为容器添加多个子节点
  • 渲染优化:针对不同场景做了渲染优化,保证丰富功能的同时实现高性能
  • 鼠标交互:支持完整的鼠标事件系统

类继承关系

Node
 └─ Sprite
     ├─ Scene
     ├─ Box
     ├─ Image
     ├─ Label
     ├─ Button
     └─ ... (其他2D显示对象)

二、属性详解

2.1 位置与尺寸属性

属性 类型 默认值 说明
x number 0 相对于父容器的X轴坐标值
y number 0 相对于父容器的Y轴坐标值
width number 0 节点的宽度(像素)
height number 0 节点的高度(像素)
displayWidth number - 对象的显示宽度,包含X轴缩放(只读)
displayHeight number - 对象的显示高度,包含Y轴缩放(只读)
// 设置位置
sprite.x = 100;
sprite.y = 200;

// 或者使用链式调用
sprite.pos(100, 200);

// 设置尺寸
sprite.width = 512;
sprite.height = 256;

// 或者使用链式调用
sprite.size(512, 256);

2.2 锚点与轴心点

**轴心点(Pivot)锚点(Anchor)**是控制精灵变换中心的重要属性。

属性 类型 说明
pivotX number X轴轴心点位置(像素),默认为0
pivotY number Y轴轴心点位置(像素),默认为0
anchorX number X轴锚点,取值范围0-1
anchorY number Y轴锚点,取值范围0-1
// 设置轴心点(以像素为单位)
sprite.pivotX = 100;
sprite.pivotY = 50;

// 或使用链式调用
sprite.pivot(100, 50);

// 设置锚点(相对于宽高的比例,0-1)
sprite.anchorX = 0.5;  // 水平中心
sprite.anchorY = 0.5;  // 垂直中心

// 或使用链式调用
sprite.anchor(0.5, 0.5);

注意:修改锚点 anchor 会自动修改轴心点 pivot,是改变轴心点的便捷方式。

2.3 变换属性

属性 类型 默认值 说明
scaleX number 1 X轴缩放比例,负数可实现水平翻转
scaleY number 1 Y轴缩放比例,负数可实现垂直翻转
rotation number 0 旋转角度(度),正数顺时针
skewX number 0 水平倾斜角度(度)
skewY number 0 垂直倾斜角度(度)
transform Matrix - 变换矩阵信息
// 设置缩放
sprite.scaleX = 2;
sprite.scaleY = 2;
// 或链式调用
sprite.scale(2, 2);

// 设置旋转
sprite.rotation = 45;  // 顺时针旋转45度

// 设置倾斜
sprite.skewX = 5;
sprite.skewY = 5;
// 或链式调用
sprite.skew(5, 5);

// 水平翻转
sprite.scaleX = -1;

// 垂直翻转
sprite.scaleY = -1;

2.4 显示属性

属性 类型 默认值 说明
visible boolean true 对象是否可见
alpha number 1 透明度,0-1,1为不透明
blendMode BlendMode null 混合模式,常用值为 “lighter”
// 设置可见性
sprite.visible = true;

// 设置透明度
sprite.alpha = 0.5;

// 设置混合模式(颜色叠加)
sprite.blendMode = "lighter";

2.5 渲染与内容属性

属性 类型 说明
texture Texture 纹理对象,设置后显示图片
graphics Graphics 绘图对象,用于绘制矢量图形
material Material 2D精灵材质
// 方式1:设置纹理
sprite.texture = texture;

// 方式2:从URL加载图片
sprite.loadImage("resources/image.png");

// 方式3:使用Graphics绘制
sprite.graphics.drawRect(0, 0, 100, 100, "#FF0000");

2.6 缓存与性能优化属性

属性 类型 说明
cacheAs string 缓存模式:无/“none”、正常/“normal”、位图/“bitmap”
drawCallOptimize boolean 是否自动优化DrawCall
autoSize boolean 是否自动计算宽高
// 缓存为位图(减少DrawCall,增加内存)
sprite.cacheAs = "bitmap";

// 开启DrawCall优化
sprite.drawCallOptimize = true;

// 自动计算宽高
sprite.autoSize = true;

2.7 交互属性

属性 类型 默认值 说明
mouseEnabled boolean false 是否接受鼠标事件
mouseThrough boolean false 空白区域是否可穿透
hitTestPrior boolean false 是否优先检测自身
hitArea IHitArea null 自定义点击区域
// 启用鼠标事件
sprite.mouseEnabled = true;

// 空白区域可穿透
sprite.mouseThrough = true;

// 优先检测自身
sprite.hitTestPrior = true;

// 设置自定义点击区域
let hitArea = new Laya.HitArea();
hitArea.hit.drawRect(0, 0, 100, 100, "#00ff00");
sprite.hitArea = hitArea;

2.8 层级属性

属性 类型 默认值 说明
zOrder number 0 Z排序,值越大越靠前
zIndex number 0 渲染排序
layer number - 遮罩层
// 设置显示层级
sprite.zOrder = 10;

2.9 其他属性

属性 类型 说明
mask Sprite 遮罩对象
scrollRect Rectangle 滚动矩形范围(带裁剪效果)
filters Filter[] 滤镜集合(已废弃,使用postProcess)
postProcess PostProcess2D 后处理效果

三、方法详解

3.1 对象管理方法

// 销毁精灵
sprite.destroy(destroyChild?: boolean): void;

// 获取父节点
sprite.parent: Sprite;

// 获取所属场景
sprite.scene: Scene;

3.2 位置设置方法(链式调用)

// 设置位置
sprite.pos(x: number, y: number): this;

// 设置轴心点
sprite.pivot(x: number, y: number): this;

// 设置锚点
sprite.anchor(x: number, y: number): this;

// 设置尺寸
sprite.size(width: number, height: number): this;

// 设置缩放
sprite.scale(x: number, y: number): this;

// 设置倾斜
sprite.skew(x: number, y: number): this;

// 链式调用示例
sprite.pos(100, 100)
     .size(200, 200)
     .scale(2, 2)
     .rotation = 45;

3.3 绘图相关方法

// 加载并显示图片
sprite.loadImage(url: string, complete?: Handler): this;

// 静态方法:根据图片URL创建Sprite
Laya.Sprite.fromImage(url: string): Sprite;

// 设置Graphics对象
sprite.setGraphics(value: Graphics, transferOwnership?: boolean): void;

3.4 坐标转换方法

// 本地坐标转全局坐标
sprite.localToGlobal(point: Point, createNewPoint?: boolean, globalNode?: Sprite): Point;

// 全局坐标转本地坐标
sprite.globalToLocal(point: Point, createNewPoint?: boolean, globalNode?: Sprite): Point;

// 本地坐标转父容器坐标
sprite.toParentPoint(point: Point): Point;

// 父容器坐标转本地坐标
sprite.fromParentPoint(point: Point): Point;

3.5 边界获取方法

// 获取在父容器坐标系的矩形显示区域
sprite.getBounds(out?: Rectangle): Rectangle;

// 获取在自己坐标系的矩形显示区域
sprite.getSelfBounds(out?: Rectangle, recursive?: boolean): Rectangle;

// 获取绘制内容的矩形区域
sprite.getGraphicBounds(realSize?: boolean, out?: Rectangle): Rectangle;

// 设置对象边界(提高性能)
sprite.setSelfBounds(bound: Rectangle): void;

3.6 碰撞检测方法

// 检测点是否在对象内
sprite.hitTestPoint(x: number, y: number): boolean;

// 获取鼠标在对象上的坐标
sprite.getMousePoint(): Readonly<Point>;
sprite.mouseX: number;
sprite.mouseY: number;

3.7 缓存刷新方法

// 刷新缓存(在cacheAs启用时)
sprite.reCache(): void;

// 重新绘制
sprite.repaint(flag?: number): void;

// 清除重绘标志
sprite.clearRepaint(): void;

3.8 拖拽方法

// 开始拖拽
sprite.startDrag(
    area?: Rectangle,       // 拖动区域
    hasInertia?: boolean,   // 是否有惯性
    elasticDistance?: number, // 橡皮筋效果距离
    elasticBackTime?: number, // 回弹时间(毫秒)
    data?: any,             // 携带的数据
    ratio?: number          // 惯性阻尼系数
): void;

// 停止拖拽
sprite.stopDrag(): void;

3.9 渲染方法

// 绘制到RenderTexture2D(推荐使用)
sprite.drawToRenderTexture2D(
    canvasWidth: number,
    canvasHeight: number,
    offsetX: number,
    offsetY: number,
    rt?: RenderTexture2D,
    isDrawRenderRect?: boolean,
    flipY?: boolean,
    clearColor?: Color,
    renderScaleX?: number,
    renderScaleY?: number
): RenderTexture2D;

// 静态方法:绘制指定Sprite
Laya.Sprite.drawToRenderTexture2D(
    sprite: Sprite,
    canvasWidth: number,
    canvasHeight: number,
    ...
): RenderTexture2D;

四、事件列表

Sprite 支持以下鼠标事件:

事件名 说明
Event.MOUSE_DOWN 鼠标按下
Event.MOUSE_UP 鼠标抬起
Event.MOUSE_MOVE 鼠标移动
Event.MOUSE_OVER 鼠标移入
Event.MOUSE_OUT 鼠标移出
Event.MOUSE_DRAG 鼠标拖拽
Event.MOUSE_DRAG_END 拖拽结束
Event.CLICK 点击
Event.RIGHT_MOUSE_DOWN 右键按下
Event.RIGHT_MOUSE_UP 右键抬起
Event.RIGHT_CLICK 右键点击
Event.DOUBLE_CLICK 双击
Event.DRAG_START 开始拖拽
Event.DRAG_MOVE 拖拽移动
Event.DRAG_END 拖拽结束
Event.DROP 放置
Event.TRANSFORM_CHANGED 变换改变
// 事件监听示例
sprite.on(Laya.Event.CLICK, this, () => {
    console.log("Sprite被点击");
});

sprite.on(Laya.Event.MOUSE_DOWN, this, (e: Laya.Event) => {
    console.log("鼠标位置:", e.stageX, e.stageY);
});

五、使用示例

5.1 创建并显示精灵

// 创建精灵实例
let sprite = new Laya.Sprite();

// 添加到舞台
Laya.stage.addChild(sprite);

// 加载图片
sprite.loadImage("resources/image.png");

// 设置位置
sprite.pos(Laya.stage.width / 2, Laya.stage.height / 2);

5.2 使用纹理显示图片

// 先加载资源
Laya.loader.load("resources/image.png").then(() => {
    let sprite = new Laya.Sprite();

    // 获取已加载的纹理
    let texture = Laya.loader.getRes("resources/image.png");
    sprite.texture = texture;

    // 设置位置并添加到舞台
    sprite.pos(100, 100);
    Laya.stage.addChild(sprite);
});

5.3 绘制矢量图形

let sprite = new Laya.Sprite();

// 绘制矩形
sprite.graphics.drawRect(0, 0, 100, 100, "#FF0000");

// 绘制圆形
sprite.graphics.drawCircle(150, 50, 30, "#00FF00");

// 绘制线条
sprite.graphics.drawLine(200, 0, 200, 100, "#0000FF", 2);

Laya.stage.addChild(sprite);

5.4 设置遮罩

let sprite = new Laya.Sprite();
sprite.loadImage("resources/image.png");
Laya.stage.addChild(sprite);

// 创建遮罩(圆形)
let mask = new Laya.Sprite();
mask.graphics.drawCircle(50, 50, 50, "#FFFFFF");
sprite.addChild(mask);

// 应用遮罩
sprite.mask = mask;

5.5 链式调用示例

let sprite = new Laya.Sprite();

// 链式设置多个属性
sprite.pos(200, 200)
     .size(100, 100)
     .pivot(50, 50)
     .scale(2, 2)
     .skew(5, 5);

Laya.stage.addChild(sprite);

5.6 拖拽功能

let sprite = new Laya.Sprite();
sprite.loadImage("resources/image.png");
Laya.stage.addChild(sprite);

// 设置拖拽区域(整个屏幕)
let dragArea = new Laya.Rectangle(0, 0, Laya.stage.width, Laya.stage.height);

// 开始拖拽
sprite.startDrag(dragArea, true, 100, 300);

5.7 自定义点击区域

let sprite = new Laya.Sprite();
sprite.loadImage("resources/image.png");

// 创建自定义点击区域
let hitArea = new Laya.HitArea();
hitArea.hit.drawCircle(50, 50, 50, "#00ff00");  // 可点击区域(圆形)
hitArea.unHit.drawRect(30, 30, 40, 40, "#ff0000"); // 不可点击区域

sprite.hitArea = hitArea;
sprite.mouseEnabled = true;

// 监听点击事件
sprite.on(Laya.Event.CLICK, this, () => {
    console.log("点击了有效区域");
});

Laya.stage.addChild(sprite);

六、性能优化建议

6.1 使用 cacheAs 优化

// 对于不常变化的复杂UI,使用cacheAs="bitmap"
sprite.cacheAs = "bitmap";
  • “none”:不缓存,默认值
  • “normal”:命令缓存,减少遍历开销
  • “bitmap”:位图缓存,大幅减少DrawCall,增加内存开销

6.2 使用 DrawCall 优化

// 自动合并同图集图片
sprite.drawCallOptimize = true;

注意:元素数量过大(>500)时会消耗较多CPU性能。

6.3 合理使用 hitArea

// 对于非矩形点击区域,使用hitArea代替宽高检测
sprite.hitArea = customHitArea;

6.4 避免频繁计算边界

// 设置固定边界,避免getBounds计算
sprite.setSelfBounds(new Laya.Rectangle(0, 0, 100, 100));

七、注意事项

  1. mouseEnabled 自动设置:监听鼠标事件时会自动将对象及父节点的 mouseEnabled 设为 true

  2. cacheAs 位图限制

    • 缓存位图最大尺寸为 2048×2048
    • 频繁重绘会增加 CPU 开销
  3. 纹理 vs Graphics

    • 显示单个图片时,使用 texture 性能最高
    • 矢量图形使用 graphics 绘制
  4. 遮罩使用

    • 遮罩对象需是显示对象的子节点
    • 只有 Spritetexture 属性支持设置 RenderTexture
  5. 坐标系统

    • 原点在左上角
    • X轴向右为正
    • Y轴向下为正

八、相关类图

Sprite (laya.display.Sprite)
├── 属性
│   ├── x, y                 位置
│   ├── width, height        尺寸
│   ├── pivotX, pivotY       轴心点
│   ├── anchorX, anchorY     锚点
│   ├── scaleX, scaleY       缩放
│   ├── rotation             旋转
│   ├── skewX, skewY         倾斜
│   ├── alpha                透明度
│   ├── visible              可见性
│   ├── texture              纹理
│   ├── graphics             绘图对象
│   ├── cacheAs              缓存
│   └── mask                 遮罩
├── 方法
│   ├── pos()                设置位置
│   ├── size()               设置尺寸
│   ├── scale()              设置缩放
│   ├── pivot()              设置轴心点
│   ├── anchor()             设置锚点
│   ├── loadImage()          加载图片
│   ├── localToGlobal()      坐标转换
│   ├── getBounds()          获取边界
│   ├── startDrag()          开始拖拽
│   └── reCache()            刷新缓存
└── 事件
    ├── CLICK                点击
    ├── MOUSE_DOWN           鼠标按下
    ├── MOUSE_UP             鼠标抬起
    ├── MOUSE_OVER           鼠标移入
    ├── MOUSE_OUT            鼠标移出
    └── ...

参考文档

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐