2021SC@SDUSC
总述
在第十篇中,我们开启对于quark-renderer中的事件中的部分js文件进行解析,主要对Eventful.js文件进行了分析。该js是事件处理的主要的文件,对于事件处理还有其他的js代码,这次我们就对其他关于事件的js进行分析。
DomEventInterceptor.js文件
简介
在该文件中,根据作者的描述,我们得知该DomEventInterceptor 类的主要功能是:拦截 DOM 标签上的原生事件,转发到 Quark-Renderer 实例上,在 QuarkRendererEventHandler 类中会把事件进一步分发给 canvas 内部的元素。需要转发的大部分 DOM 事件挂载在 canvas 的外层容器 div 上面,例如:click, dbclick, contextmenu 等;少部分 DOM 事件直接挂载在 document 对象上,例如:mousemove, mouseout。因为在实现拖拽和键盘交互的过程中,鼠标指针可能已经脱离了 canvas 所在的区域。
setTouchTimer
该方法的作用是防止鼠标事件在 Touch 事件之后触发,在该函数中调用了setTimeout方法,这个方法是设置定时功能以便能够被覆盖。 某些浏览器(Safari、IE 8、phantomjs)需要这个 hack。在该方法中,处理一个匿名函数,完成scope.touching = false;scope.touchTimer = null;
在使用事件处理的时候,需要注意这两点:
- 移动端的浏览器会在触摸之后 300ms 派发鼠标事件。
- Android 上的 Chrome 浏览器会在长按约 650ms 之后派发 mousedown 事件。所以最终结果就是:禁止鼠标事件 700ms。
function setTouchTimer(scope) {
scope.touching = true;if (scope.touchTimer != null) {
clearTimeout(scope.touchTimer);scope.touchTimer = null;}scope.touchTimer = setTimeout(function () {
scope.touching = false;scope.touchTimer = null;}, 700);
}
localDOMHandlers对象
这是一个处理者对象,其中local指的是Canvas内部的区域。该对象处理的是有关鼠标的一些处理,比如mouseout、touchstart、touchmove、touchend、pointerdown、pointermove、pointerup、pointerout等操作,以及对应他们的处理函数,下面我们就他们进行分别讨论:
mouseout
该方法时对于鼠标移出时调用的函数,处理的时,首先调用eventUtil的normalizeEvent函数,该函数的作用是将输入事件的坐标标准化, 如果使用鼠标滚轮,获得e.qrDelta
。该函数的返回结果为 一个 {UIEvent} ,即规范化的本地UIEvent。然后再mouseout函数中处理element和nodeType,同时忽略包含在root中的dom引起的mouseout,最后调用this的trigger函数,将mouseout和event事件传入,这里的 trigger() 方法是从 Eventful 里面的 mixin 进来的,调用这个 trigger() 方法的时候,是在 QuarkRender 内部,也就是 canvas 里面触发事件。而这里实现的目的是:把接受到的 HTML 事件转发到了 canvas 内部。对于trigger方法,我们在上一节已经学习到了,在eventfull.js中的一个方法,作用就是触发一个事件。
mouseout: function (event) {
event = eventUtil.normalizeEvent(this.dom, event);let element = event.toElement || event.relatedTarget;if (element !== this.dom) {
while (element && element.nodeType !== 9) {
if (element === this.dom) {
return;}element = element.parentNode;}}this.trigger('mouseout', event);},
touchstart
该函数是对触摸开始时调用的函数,一开始也调用eventUtil中的normalizeEvent函数,进行event的标准化,这里不应该禁用默认的鼠标行为,例如,页面可能需要被滑动。然后调用一个markTouch函数,该函数的作用是标记触摸,这在区分触摸和 鼠标事件。调用processGesture处理手势,然后调用mousemove.cal和mousemove.call,该函数的作用是为了使触摸设备和鼠标设备的事件监听器一致,我们在触摸设备中模拟 “mouseover–>mousedown”。所以我们在这里触发mousemove'
(在里面触发mouseover’),然后再触发 `mousedown’。
touchstart: function (event) {
event = eventUtil.normalizeEvent(this.dom, event);markTouch(event);this._lastTouchMoment = new Date();this.handler.processGesture(event, 'start');localDOMHandlers.mousemove.call(this, event);localDOMHandlers.mousedown.call(this, event);},
touchmove
该函数处理触摸移动,该函数中一开始也需要对事件进行标准化,然后同样需要调用markTouch
来标记触摸,调用mousemove.call(this,event),这里说明一下,鼠标移动应该总是被触发,无论是否有gestrue事件,因为鼠标移动和捏住可能同时被使用。
touchmove: function (event) {
event = eventUtil.normalizeEvent(this.dom, event);markTouch(event);this.handler.processGesture(event, 'change');localDOMHandlers.mousemove.call(this, event);},
touched
该函数处理的是在触摸以后应该处理的事情,起初也是三个函数的调用,分别对事件标准化,然后触摸标记,接着处理手势,标记为end
,然后调用mouseup.call,接着判断当前时间减去最晚触摸时刻的值与触摸延迟进行比较,尽管mousemove
(mouseover
在touchstart
中被触发了,但在这里不要触发mouseout
。这似乎不合逻辑,但通过这种机制,我们可以方便地在PC和触摸设备上实现 “悬停样式”,只需监听mouseover
来添加 “悬停样式”,监听mouseout
来删除元素上的 “悬停样式”,无需任何额外的兼容代码。(mouseout
不会在`touchend’中被触发,所以 "hover style "将保留在用户视图中)无论是否有gestrue事件,点击事件应该总是被触发的。系统点击是不能被阻止的。
touchend: function (event) {
event = eventUtil.normalizeEvent(this.dom, event);markTouch(event);this.handler.processGesture(event, 'end');localDOMHandlers.mouseup.call(this, event);if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) {
localDOMHandlers.click.call(this, event);}},
总结
以上我们对于DomEventInterceptor.js中的一些方法和对象进行了学习。总而言之,本次分析的主要是对于鼠标从移入到触摸再到点击事件的分析,还有一些没有看完,下次我们对剩余的函数进行学习。