leafer-ui icon indicating copy to clipboard operation
leafer-ui copied to clipboard

同时点两个元素时,只有一个元素触发回调

Open parox2014 opened this issue 2 months ago • 3 comments

环境:

微信小程序,@leafer-game/miniapp,v1.9.12

出现的问题:

给两个元素绑定PointerEvent.Down事件,当同时点击这两个元素时,只有其中一个触发了回调,并且触发了两次,另外一个无反应。当单独点这两个元素时,都会触发回调

代码如下:

import {
  IGameLoop,
  IGameState,
  PointerEvent,
  IRobotInputData,
} from '@leafer-game/miniapp';
import { ElapsedTime, GameSpirit } from '@/games2/core';

import lightChainImage from './assets/kr-light-chain.png';

export class ElectronicWall extends GameSpirit implements IGameLoop {

  get powerOn(): boolean {
    return this.currentState instanceof PowerOnState;
  }
  constructor(data: IRobotInputData) {
    super({
      ...data,
      height: 42,
      robot: [
        {
          url: require('@/games2/components/kill-virus/assets/wall-def.png'),
          size: {
            width: 337,
            height: 84,
          },
          total: 1,
        },
        {
          url: lightChainImage,
          size: {
            width: 337,
            height: 84,
          },
          total: 1,
        },
        {
          url: lightChainImage,
          size: {
            width: 337,
            height: 84,
          },
          offset: {
            x: 100,
            y: 0,
          },
          total: 1,
        },
      ],
      actions: {
        powerOff: 0,
        powerOn: [1, 2],
      },
      action: 'powerOff',
    });
    this.waitParent(() => {
      this.parent?.on(PointerEvent.DOWN, this.onPointerDown.bind(this));
      this.width = this.parent?.width;
    });
    this.setState(new PowerOffState());
  }
  onUpdate() {
    const state = this.currentState.onUpdate?.(this);
    this.setState(state);
  }
  onPointerDown(e:PointerEvent) {
    const state = this.currentState.handleInput?.(this);
    console.log('innerId:'+this.innerId,e.multiTouch)
    this.setState(state);
  }
}

export class PowerOffState implements IGameState {
  name:string='powerOff';
  handleInput() {
    return new PowerOnState();
  }
  enter(wall: ElectronicWall) {
    wall.action = 'powerOff';
    wall.opacity = 0.5;
  }
}

export class PowerOnState extends ElapsedTime implements IGameState {
  name:string='powerOn';
  duration: number = 200;
  onUpdate() {
    if (this.elapsedTime >= this.duration) {
      return new PowerOffState();
    }
  }
  enter(wall: ElectronicWall) {
    wall.action = 'powerOn';
    wall.opacity = 1;
  }
}

在页面上实例化了两个ElectronicWall,同时点击这两个元素时,输出:

$ innerId:2 false
$ innerId:2 true

innerId一样,说明是同一个元素回调了两次

分开点击时输出:

$ innerId:2 false
$ innerId:4 false

parox2014 avatar Oct 28 '25 09:10 parox2014

默认的PointerEvent事件只会取第一个touch点,所以会出现你观察到的现象,我后面看看能不能优化一下。

多点触屏分别点中了哪些元素也可以自己监听TouchEvent实现(leafer提供了pick拾取元素方法和模拟交互事件): https://www.leaferjs.com/ui/reference/event/simulation.html https://www.leaferjs.com/ui/reference/UI/pick.html

leaferjs avatar Oct 29 '25 01:10 leaferjs

默认的PointerEvent事件只会取第一个touch点,所以会出现你观察到的现象,我后面看看能不能优化一下。

多点触屏分别点中了哪些元素也可以自己监听TouchEvent实现(leafer提供了pick拾取元素方法和模拟交互事件): https://www.leaferjs.com/ui/reference/event/simulation.html https://www.leaferjs.com/ui/reference/UI/pick.html

做游戏同时点击多个元素是很常见的,期待优化,谢谢。

另外你说的自己监听TouchEvent事件,意思是不需要调用leafer.receiveEvent,把Touch事件传给leafer,而是通过Touch的坐标点,获取到元素,手动触发元素上的事件?

parox2014 avatar Oct 29 '25 01:10 parox2014

  1. 好的,后面优化一下
  2. 具体需要看一下模拟交互的文档,可以模拟点击(针对多个touch点可以分别调用pointerDown()等方法),如果自己处理touch事件的传递,确实是不能同时再使用leafer.receiveEvent

leaferjs avatar Oct 29 '25 02:10 leaferjs