Egret 2D(7)之事件

事件处理机制

在Egret中,事件模型定义了一套标准的生成和处理事件消息的方法,使程序中的对象可以相互交互,通信,保持自身状态和相应变化。

简单的说,数据的提供者只管发出数据对象,只要确保数据对象是 egret.Event 类或者子类的实例即可。这种数据对象 ,称为事件(Event)数据对象的发出者,称之为事件发送者(Event dispatcher)。同时,接受事件的对象,称为 事件侦听者(Event listener)。

以下是一个简单的例子:

当我们想要和男(女)朋友约会的时候,通常都会有一个约会的发起者,同时还有个一个约会对象。那么这个邀请过程,就是一个典型的事件过程。

男朋友是事件发送者,邀请约会就是男朋友发送的事件。而女朋友就是事件侦听器。

这个事件,包含三条主要内容:事件的类型,事件的目标,事件的相关数据事件的类型就是邀请约会,女朋友会 根据事件的不同,来执行不同的任务。比如,事件是“邀请约会”,那么女朋友可能会执行,梳妆打扮,然后赴约。如果事件 是“肚子饿了”,那么女朋友会执行买菜做饭。

事件的目标,就是事件的发送者。如果没有这个信息,那么女朋友接到事件后,就无法知道是谁要约她,或者是谁饿了。

事件的数据,就是事件所要包含的信息。上面的约会事件中,事件的信息可以包括事件,地点,干什么。同理,“肚子饿了”这个事件,要包含的信息是想吃些什么,在家里吃还是去外面吃等等。当然,也有一些事件是不包含信息的,例如“捶背”,事件 接受者只要收到这个事件,直接执行就可以了。

事件的执行流程

事件机制包含4个步骤:注册侦听器,发送事件,侦听事件,移除侦听器。这四个步骤是按照顺序来执行的。

注册侦听器,即指定事件由哪个对象的哪个方法来接受。在约会的例子中,我们指定由男朋友来发送事件,由女朋友来接受事件。

只有在注册侦听器后,发送的事件才能被侦听。而且发送的事件必须和侦听器事件的类型匹配。在发送事件后,侦听器才能侦听到事件。

Event类

Event类是所有事件类的基类。当创建一个自定义事件的时候,事件应该继承自Event类。同时Event类也包含一些事件。这些事件通常与显示列表,显示对象的状态有关

在使用Event类时,有以下几个属性与方法需要注意:

  • 首先是构造函数中的三个参数,type、bubbles和cancelable
  •  type指定事件的类型,在“约会”的例子中,type事件类型为“DATE”。我们经常使用的事件类型有“ADDED”、“COMPLETE”等。自定义事件时type类型自己指定。
  • bubbles是指定事件是否参与事件流的冒泡阶段,关于事件流,会在后面的小节中介绍。
  • cancelable表示是否可以取消与事件关联的默认动作。
  • 另外还需要关注的属性是target,这个属性表示事件的目标,也就是事件的发送者。其他的一些方法都与事件流有关,后面的内容会进行详细介绍。

事件侦听器

事件侦听器也就是事件的处理者,负责接收事件携带的信息,并在接收到该事件后执行特定的代码。

Egret中,事件的侦听器必须是一个函数。事件的发送者必须是 egret.EventDispatcher 类或者子类的实例。只有事件发送者才能侦听事件,并且可以注册侦听器。

侦听事件分为两个部分,第一是建立侦听器,侦听器可以是独立的函数,也可以是某一个对象的方法。第二步是注册侦听器,使用事件发送者的 addEventListener() 将相应的事件分配给侦听器。

创建(建立)侦听器

侦听器必须是函数,它可以是一个独立函数,也可以是一个实例的方法。侦听器必须有一个参数,并且这个参数必须是 Event 类实例或其子类的实例, 同时,侦听器的返回值必须为空(void)。范例代码如下

listenerName(evt:Event):void {...}

注:一般定义在事件侦听者中,也就是事件的接收者对象中。

public getDate(evt:DateEvent)
    {
        console.log("得到了" + evt.target.name + "的邀请!" );
        console.log("事件侦听者处理事件");
    }

注册侦听器与移除侦听器

只有事件的发送者才可以注册侦听器,事件的发送者必须是 EventDispatcher 类或其子类的实例。移除侦听器也同理,通常情况下,注册侦听器与移除侦听器都是成对出现

注册侦听器:

事件发送者.addEventListener(事件类型, 侦听器, this);

注册侦听函数的定义:

public addEventListener(type:string, listener:Function, thisObject:any, useCapture:boolean = false, priority:number = 0)

  • type:事件类型,必选。
  • listener:用来处理事件的侦听器,必选。
  • thisObject:作用域,必选,一般填写this。因为TypeScript与JavaScript的this作用域不同,其this指向也会不同。如果不填写this的话,那么编译后的代码会发生错误。 关于this的问题,可以学习JavaScript中的原型链。
  • useCapture: 确定侦听器是运行于捕获阶段还是运行于冒泡阶段,可选。设置为 true,则侦听器只在捕获阶段处理事件,而不在冒泡阶段处理事件。设置为 false,则侦听器只在冒泡阶段处理事件。
  • priority: 事件侦听器的优先级,可选。优先级由一个带符号的整数指定。数字越大,优先级越高。优先级为 n 的所有侦听器会在优先级为 n -1 的侦听器之前得到处理。如果两个或更多个侦听器共享相同的优先级,则按照它们的添加顺序进行处理。默认优先级为 0。

移除侦听器:

事件发送者.removeEventListener(事件类型, 侦听器, this);

检测侦听器

如果需要在逻辑中检测某一个事件发送者是否注册了侦听器,有两个方法可以使用。 一个是 hasEventListener ,另外一个是 willTrigger 。两个方法执行效果相同,都是判断一个事件发送者是否注册了某一个类型的事件。

如果该事件类型已经被注册过,返回 true,如果没有被注册过,返回 false

事件发送者.hasEventListener(事件类型);

TouchEvent的启动开关

TouchEvent的启动开关 touchEnabled 指定此对象是否接收触摸或其他用户输入。默认值为 false,实例将不接收任何触摸事件(或其他用户输入事件)。如果将 touchEnabled设置为 true,则显示对象实例将会接收触摸事件或其他用户输入事件。要更改显示对象的所有子级的 touchEnabled 行为,请使用 DisplayObjectContainer.touchChildren

实际使用过程,如果某些显示对象需要侦听TouchEvent,请先打开:

显示对象实例.touchEnabled = true;

简单理解就是让显示对象能够响应手势事件

自定义事件(约会例子)

实现约会

事件类


//自定义事件类
//注意事件要继承egret.Event类
class DateEvent extends egret.Event{
	//注意构造函数接受三个参数                
	public constructor(type:string, bubbles:boolean, cancelable:boolean) {
		//注意super中的参数。
		//事件类接受三个参数后传给super调用父构造函数
		super(type,bubbles,cancelable);
	}

    //定义静态事件类型type,为什么要静态?给发送者直接访问并传入作为本类的构造函数的参数type
	public static YUEHUI:string="约会";//事件type为约会
	//定义约会地点
	public address:string;
	//定义约会时间
	public time:string;

}

事件发送者---约会中的男朋友

//男朋友类--事件发送者
class Boy extends egret.Sprite{
	public constructor() {
		super();
	}
	public sendEvent(){
		//实例化约会事件对象
		//其中DateEvent.YUEHUI是访问事件类中的静态成员变量YUEHUI作为事件的类型type
		let dataEvent:DateEvent=new DateEvent(DateEvent.YUEHUI,false,false);
		//添加事件的数据---约会地点
		dataEvent.address="厦门鼓浪屿";
		//添加事件的数据--约会时间
		dataEvent.time="晚上7点";
		//发送要求事件
		this.dispatchEvent(dataEvent);
	}
}

事件接收者--女朋友类

接受事件信息后处理

//女朋友类--事件接受者对象---事件侦听者
class Girl extends egret.Sprite{
	public constructor() {
		super();
	}

	//创建侦听器
	public goYueHui(evt:Event):void{
		/*
			这里as xxx和<xx>是ts的类型断言。这里如果不这样写会编译报错,其实代码没有错的。
			这是因为ts是静态语言。简单就是一开始evt并没有定义一些属性,使我们动态设置的。

			as 语法和<>尖括号语法的作用是一样的
			
		*/
		console.log("接受了"+(evt as any).target.name+"的邀请");
		console.log("约会地点:"+(evt as any).address);	
		console.log("约会时间:"+(<any>evt).time);	
	}
}

调用触发发送事件

//实例化男朋友
            let boy:Boy=new Boy();
            boy.name="男朋友";
            //实例化女朋友
            let girl:Girl=new Girl();
            girl.name="女朋友";
            //注册侦听器
            boy.addEventListener(DateEvent.YUEHUI,girl.goYueHui,girl);//参数为事件类型,处理事件的侦听器,作用域
            //男朋友发送要求
            boy.sendEvent();
            //约会邀请完成后,移除侦听器
            boy.removeEventListener(DateEvent.YUEHUI,girl.goYueHui,girl);

极简自定义事件

下面演示了一个自定义事件,该事件直接new了一个事件的父类(Event),且该事件不需要事件信息。直接根据条件触发发送事件。“jumpGame”简单理解就是时间类型(也可理解事件名字)

事件发送者:

let event=new egret.Event("jumpGame",false,false);                                                                                                                                                                                                                                                
//点击事件
btnWrap.addEventListener(egret.TouchEvent.TOUCH_TAP,()=>{
	//发送事件
	this.dispatchEvent(event);
},this);

事件接受者和监听者:

  this.game.addEventListener("jumpGame",()=>{
         //处理事件
  },this);

触摸事件

对于移动游戏,触摸事件是最常用的用户交互事件类型。Egret 为触摸事件设置了专门的触摸事件类egret.TouchEvent

其包含的事件类型主要有:

  • TOUCH_BEGIN:当用户第一次触摸启用触摸的设备时(例如,用手指触摸配有触摸屏的移动电话或平板电脑)触发
  • TOUCH_CANCEL:由于某个事件取消了触摸时触发
  • TOUCH_END:当用户移除与启用触摸的设备的接触时(例如,将手指从配有触摸屏的移动电话或平板电脑上抬起)触发
  • TOUCH_MOVE:当用户触碰设备并移动时进行触发,而且会连续触发,直到接触点被删除
  • TOUCH_TAP:当用户在触摸设备上与开始触摸的同一 DisplayObject 实例上抬起接触点时触发(相当与点击事件)

在Egret中使用触摸事件时,需要打开显示对象的触摸事件开关,即将该显示对象的touchEnabled属性设置为true

   //设置显示对象可以相应触摸事件
        spr1.touchEnabled = true;
        //注册事件
        spr1.addEventListener( egret.TouchEvent.TOUCH_TAP, this.onTouch, this );
...........


    private onTouch( evt:egret.TouchEvent )
    {
       ...........
    }

猜你喜欢

转载自my.oschina.net/u/3112095/blog/1785912
今日推荐