Laya.InputManager 输入管理器

版本: v3.3.6 | 模块: laya/events/InputManager


概述

Laya.InputManager 是 LayaAir 引擎的输入事件管理类,负责处理鼠标、触摸和键盘等输入事件。


静态属性

开关控制

属性 类型 默认值 说明
multiTouchEnabled boolean true 是否开启多点触控支持
mouseEventsEnabled boolean true 是否开启鼠标/触摸事件
keyEventsEnabled boolean true 是否开启键盘事件
clickTestThreshold number 10 鼠标按下和弹起位置距离阈值,超过此值不视为点击

鼠标位置

属性 类型 说明
mouseX number canvas 上鼠标的 X 坐标
mouseY number canvas 上鼠标的 Y 坐标
lastMouseTime number 上一次鼠标事件的时间

触摸相关

属性 类型 说明
touchCount number (只读) 当前触摸数量
touches TouchInfo[] (只读) 当前触摸信息数组
touchTarget Node (只读) 当前触摸目标节点
lastTouchId number 上一次触摸事件的 ID

回调

属性 类型 说明
onMouseDownCapture Delegate (只读) 在处理 MOUSE_DOWN 事件之前调度,可用于预处理按下事件

静态方法

实例获取

static get inst(): InputManager

获取 InputManager 单例实例。


触摸位置

static getTouchPos(touchId?: number): Point

获取指定触摸点的位置。

参数:

  • touchId: 触摸点 ID,不提供则返回 lastTouchId 对应的触摸点位置

返回: Point - 触摸点的位置


键盘检测

static hasKeyDown(key: string | number): boolean

返回指定键是否被按下。

参数:

  • key: 键值(支持 key 字符串或 keyCode 数字)

返回: boolean - 是否被按下

常用键值:

按键 key 值 keyCode 按键 key 值 keyCode
W "w" 87 A "a" 65
S "s" 83 D "d" 68
空格 " " 32 ESC "Escape" 27
Shift "Shift" 16 Enter "Enter" 13

取消点击

static cancelClick(touchId?: number): void

取消指定触摸点的点击事件(将 clickCancelled 设为 true)。

参数:

  • touchId: 要取消的触摸事件 ID,不提供则使用 lastTouchId

实例方法

获取节点

getNodeUnderPoint(x: number, y: number): Node

获取指定坐标下的节点。

参数:

  • x: X 坐标值(已除以 clientScaleX
  • y: Y 坐标值(已除以 clientScaleY

返回: Node - 该点下的节点,如果没有找到节点则返回舞台


getSpriteUnderPoint(sp: Sprite, x: number, y: number): Sprite

获取在相对 Sprite 指定坐标下的 Sprite。


getSprite3DUnderPoint(x: number, y: number): Node

获取 3D 场景中指定坐标下的 3D 节点(源码中返回 null,由子类实现)。


碰撞检测

hitTest(sp: Sprite, x: number, y: number, editing?: boolean): boolean

检测指定坐标是否命中 Sprite。

命中规则(源码逻辑):

if (sp.width > 0 && sp.height > 0 || mouseThrough || hitArea) {
    if (!mouseThrough)
        isHit = (0, 0, sp.width, sp.height).contains(x, y);
    else
        isHit = sp.getGraphicBounds(false).contains(x, y);
}

重要说明

graphics 绘图必须设置 size

使用 graphics.drawCirclegraphics.drawRect 等方法绘制的内容不会自动设置 Sprite 的宽高

hitTest 方法检测条件: sp.width > 0 && sp.height > 0

因此必须手动调用 size() 设置宽高,否则鼠标事件无法正确检测。

// ❌ 错误:width=0, height=0,hitTest 返回 false
const sprite = new Laya.Sprite();
sprite.graphics.drawRect(0, 0, 100, 100, "#FF0000");
console.log(sprite.width, sprite.height); // 0, 0

// ✅ 正确:设置 size 后
sprite.size(100, 100);
console.log(sprite.width, sprite.height); // 100, 100

使用示例

示例 1: 鼠标位置追踪

export class MouseTrackExample {
    private sprite: Laya.Sprite;

    constructor() {
        Laya.init(800, 600).then(() => {
            this.init();
        });
    }

    private init(): void {
        this.sprite = new Laya.Sprite();
        this.sprite.graphics.drawCircle(0, 0, 20, "#FF0000");
        this.sprite.size(40, 40);  // 必须设置 size
        Laya.stage.addChild(this.sprite);

        Laya.stage.on(Laya.Event.MOUSE_MOVE, this, this.onMouseMove);
    }

    private onMouseMove(): void {
        this.sprite.x = Laya.InputManager.mouseX;
        this.sprite.y = Laya.InputManager.mouseY;
    }
}

示例 2: 多点触控

export class MultiTouchExample {
    private text: Laya.Text;
    private touches: Laya.Sprite[] = [];

    constructor() {
        Laya.init(0, 0).then(() => {
            this.init();
        });
    }

    private init(): void {
        this.text = new Laya.Text();
        this.text.fontSize = 30;
        this.text.color = "#FFFFFF";
        Laya.stage.addChild(this.text);

        Laya.timer.frameLoop(1, this, this.update);
    }

    private update(): void {
        this.text.text = `触控点数量: ${Laya.InputManager.touchCount}`;

        for (let i = 0; i < Laya.InputManager.touches.length; i++) {
            let touchSprite = this.touches[i];
            if (!touchSprite) {
                touchSprite = new Laya.Sprite();
                touchSprite.graphics.drawCircle(0, 0, 30, "#00FF00");
                touchSprite.size(60, 60);  // 必须设置 size
                Laya.stage.addChild(touchSprite);
                this.touches[i] = touchSprite;
            }

            const pos = Laya.InputManager.getTouchPos(i);
            touchSprite.pos(pos.x, pos.y);
        }
    }
}

示例 3: 键盘控制

export class KeyboardControlExample {
    private player: Laya.Sprite3D;
    private speed: number = 0.1;

    constructor() {
        Laya.init(0, 0).then(() => {
            this.init();
        });
    }

    private init(): void {
        // 创建玩家对象...
        Laya.timer.frameLoop(1, this, this.onUpdate);
    }

    private onUpdate(): void {
        const movement = new Laya.Vector3();

        if (Laya.InputManager.hasKeyDown("w")) movement.z -= this.speed;
        if (Laya.InputManager.hasKeyDown("s")) movement.z += this.speed;
        if (Laya.InputManager.hasKeyDown("a")) movement.x -= this.speed;
        if (Laya.InputManager.hasKeyDown("d")) movement.x += this.speed;

        if (movement.length() > 0) {
            this.player.transform.translate(movement);
        }
    }
}

示例 4: 取消点击判定

export class CancelClickExample {
    private sprite: Laya.Sprite;

    constructor() {
        Laya.init(800, 600).then(() => {
            this.init();
        });
    }

    private init(): void {
        this.sprite = new Laya.Sprite();
        this.sprite.graphics.drawRect(0, 0, 100, 100, "#FF0000");
        this.sprite.size(100, 100);
        Laya.stage.addChild(this.sprite);

        this.sprite.on(Laya.Event.MOUSE_MOVE, this, () => {
            // 鼠标移动时取消点击判定
            Laya.InputManager.cancelClick();
        });

        this.sprite.on(Laya.Event.CLICK, this, () => {
            console.log("只有不拖动才会触发");
        });
    }
}

常见问题

Q: 用 graphics 画图为什么不触发鼠标事件?

必须设置 size(),因为 hitTest 检测条件是 sp.width > 0 && sp.height > 0

Q: 为什么 hasKeyDown 检测不到按键?

确保 Laya.InputManager.keyEventsEnabled = true

Q: 如何禁用多点触控?

Laya.InputManager.multiTouchEnabled = false;

Q: 如何判断是点击还是拖拽?

源码中 clickCancelled 在移动距离超过 clickTestThreshold 时设为 true,可通过 Laya.InputManager.cancelClick() 手动取消。


事件流程

源码中的事件处理流程:

  1. 鼠标事件 (handleMouse):

    • mousedownhandleMouse(ev, 0)Event.MOUSE_DOWN
    • mouseuphandleMouse(ev, 1)Event.MOUSE_UPEvent.CLICK
    • mousemovehandleMouse(ev, 2)Event.MOUSE_MOVE
    • wheelhandleMouse(ev, 4)Event.MOUSE_WHEEL
  2. 触摸事件 (handleTouch):

    • touchstarthandleTouch(ev, 0)Event.MOUSE_DOWN
    • touchendhandleTouch(ev, 1)Event.MOUSE_UPEvent.CLICK
    • touchmovehandleTouch(ev, 2)Event.MOUSE_MOVE
  3. 键盘事件 (handleKeys):

    • keydown / keyupEvent.KEY_DOWN / Event.KEY_UP

相关类

说明
Laya.Event 事件类型常量定义
Laya.TouchInfo 触摸信息结构
Laya.Keyboard 键盘事件常量
Logo

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

更多推荐