重庆熊猫 Loading

ExtJS-事件管理-触屏事件和手势事件(Touch Events & Gestures)

更新记录
2022年7月26日 发布。
2022年7月16日 从笔记迁移到博客。

ExtJS教程汇总:https://www.cnblogs.com/cqpanda/p/16328016.html

触屏事件和手势事件(Touch Events & Gestures)

触屏事件说明

除DOM事件和组件事件外,Ext JS还提供手势识别事件功能,常用于移动端
除标准DOM事件外,还支持合成手势事件
有三种主要类型的事件:点击(Pointer)、触摸(Touch)、鼠标(Mouse)

分别支持:开始、移动、结束

Event	Touch	Pointer	Mouse
Start	touchstart	pointerdown	mousedown
Move	touchmove	pointermove	mousemove
Stop	touchend	pointerup	mouseup

通过合成事件、ExtJS框架可以实现更复杂事件
比如拖动、滑动、长按、收缩、旋转和点击

Ext.get('myElement').on('longpress', handlerFunction);

通过拦截所有3种类型的事件,鼠标、点击、触摸

手势事件说明

Ext JS允许任何手势响应任何类型输入
这不仅意味着所有的手势都可以用触摸输入触发
而且所有的单点手势(点击、刷卡等)也可以用鼠标触发
这就产生手势事件系统,可以无缝地跨设备工作,而不必考虑输入类型
目前支持以下类型的手势

image
image

Gesture		Events
Tap		tap, tapcancel
DoubleTap	singletap, doubletap
LongPress	longpress
Drag		dragstart, drag, dragend, dragcancel
Swipe		swipestart, swipe, swipecancel
Pinch		pinchstart, pinch, pinchend, pinchcancel
Rotate		rotatestart, rotate, rotateend, rotatecancel
EdgeSwipe	edgeswipe, edgeswipestart, edgeswipeend, edgeswipecancel

在某些情况下,应用程序只需要在特定类型的输入(鼠标或触摸)触发时监听手势,而忽略另一个。ExtJS在事件对象上提供pointerType属性,用于检测导致事件的输入类型

el.on('drag', function(e) {
    if (e.pointerType === 'touch') {
        // only handle touch-drag, and ignore mouse-drag
    }
});

事件统一化(Event normalization)

To support touch-screen devices, the framework automatically translates touch-screen events into their equivalent mouse events for us. This is called event normalization

As developers, we don’t need to worry about the extra coding
All we have to do is consider the event being used by a mouse

For instance, mousedown will seamlessly be translated to touchdown and pointerdown for us

比如我们写一个鼠标按下事件

myDivElement.on('mousedown', function(e) {
    // event handling logic here
});

当在移动设备访问时,ExtJS会自动转为:

myDivElement.on('touchstart', function(e) {
    // event handling logic here
});

或者

myDivElement.on('pointerdown', function(e) {
    // event handling logic here
});

注意:Ext JS 5 does not perform normalization on events such as mouseover, mouse out, mouse enter, and mouse leave, so when developing applications, we need to look for alternative events to implement these interactions

绑定事件

Ext.get('myDivElement').on('pinch', doSomething);

事件传播(Event Propagation)过程

ExtJS事件通过框架传播的方式与DOM事件在浏览器中自然传播的方式几乎相同
不同之处在于,该框架使用委托事件模型来支持手势识别
这意味着事件在单独的传播阶段传递给DOM元素
该阶段发生在事件已经在DOM级别完成传播之后

image

事件本地传播(Native Propagation)

当浏览器通过DOM层次结构传播事件时,将调用直接附加到DOM元素的事件侦听器
虽然理解Native传播机制很有帮助,但通常应避免在Ext JS中直接附加DOM侦听器,原因如下:
直接侦听器与其他侦听器顺序不一致
从直接连接的侦听器调用stopPropagation可以防止手势识别的发生,并防止随后的合成传播
在某些情况下,可能需要将侦听器直接附加到DOM元素,例如,在将Ext JS与其他框架一起使用时,需要解决一个问题。这可以使用委托事件delegated选项来完成

el.on({
    mousedown: function() {
        Ext.Msg.alert('mousedown fired - native capture phase');
    },
  // careful when using delegated: false! this can have unintended side effects
   delegated: false,
   // use the capture option to listen in the capture phase
   capture: true
});

DOM级(Native)的传播分为两个阶段
首先是捕获阶段,在捕获阶段中,事件从dom的顶部被分派到每个元素,从窗口对象开始,一直到作为事件目标的元素
捕获阶段之后,会出现气泡阶段,在此阶段中,事件首先传递到目标元素,然后传递到其祖先,直到到达层次结构的顶部
默认情况下,侦听器在传播的冒泡阶段触发,但也设置在捕获阶段侦听

手势识别阶段(Gesture Recognition)

在本地事件冒泡到Window对象之后,Ext JS执行手势识别
然后它可以合成一个或多个手势事件,然后必须在整个DOM中传播

监听指定的手势
有时,同一层次中的元素可能在监听相互冲突的手势。比如元素A包含元素B
假设元素A正在监听swipe,而它的子元素B正在监听drag
当元素B处理dragstart事件时,它可能希望防止将当前手势解释为swipe
因为元素a的swipe处理程序可能会干扰元素B的drag处理程序
要做到这一点,它必须通过调用事件对象上的claimpostegy方法来“声明”拖动手势

el.on('dragstart', function(e) {
    e.claimGesture();
});

合成事件传播阶段(Synthetic Propagation)

手势识别步骤完成后,框架将发送原始的DOM事件(如mousedown或touchmove)以及任何手势事件(如由于DOM事件而被识别的拖动或滑动)
与本地(Native)事件一样,合成事件传播也发生在两个阶段,捕获和气泡阶段
合成传播是框架内所有事件侦听器的默认设置,建议用于使用Ext JS的应用程序
使用合成传播可确保事件与其他事件按正确的顺序触发,并避免由于某种原因停止传播时出现意外
开发人员不需要做任何事情来实现合成传播,因为这是默认的
可以使用以下方式使用合成传播(比如on方法):

el.on('mousedown', function() {
    Ext.Msg.alert('mousedown fired - synthetic bubble phase');
});

使用capture选项可用于在捕获阶段侦听:

el.on({
    mousedown: function() {
        Ext.Msg.alert('mousedown fired - synthetic capture phase');
    },
    capture: true
});

停止事件传播(Stopping Propagation)

停止事件传播可以在任何点停止,无论是本地(Native) 事件或合成(Synthetic)事件,无论是捕获阶段还是冒泡阶段
这可以防止将事件分发到尚未接收到它的任何元素,并防止执行任何挂起的捕获或气泡阶段

实例:停止事件传播到父元素

parentEl.on('mousedown', function() {
    // never fires because child element in bubble phase stops propagation of mousedown
    Ext.Msg.alert('mousedown fired on child');
});

el.on('mousedown', function(e) {
    Ext.Msg.alert('mousedown fired on child');

    // immediately stop propagating the event any further
    e.stopPropagation();
});

实例:停止事件传播在捕获阶段

el.on({
    mousedown: function(e) {
        Ext.Msg.alert('mousedown - capture phase');
//stopping propagation during the capture phase causes the entire
//bubble phase to be skipped
        e.stopPropagation();
    },
    capture: true
});

el.on('mousedown', function() {
// never fires because propagation of mousedown event was stopped prior to
// bubble phase
    Ext.Msg.alert('mousedown - bubble phase');
});

浏览器处理的手势(Browser-Handled Gestures)

浏览器会自动处理某些触摸手势,并执行默认操作(如滚动或缩放)
这些动作被称为“触摸动作”,浏览器通常实现以下触摸操作:
Gesture Touch Action
drag (horizontal) 水平滚动(horizontal scroll)
drag (vertical) 垂直滚动(vertical scroll)
pinch 缩放(zoom)
doubletap 缩放(zoom)
ExtJS应用程序为这些手势中的任何一个实现了自己的处理
在需要时可以在处理手势时禁用浏览器的一个或多个默认触摸操作

// instruct the browser not to scroll while "el" is being dragged
el.setTouchAction({
    panX: false,
    panY: false
});

在处理组件时,通常应该避免直接在其元素上调用setTouchAction,而是使用组件的touchAction选项进行配置

Ext.create('Ext.panel.Panel', {
    touchAction: {
        panY: false,
        body: {
            pinchZoom: false
        }
    },
    listeners: {
        drag: function(e) {
        // handle drag on the panel's main element
        },
        pinch: {
            element: 'body',
            fn: function(e) {
            // handle pinch on the panel's body element
            }
        }
    }
});

长按拖动(Longpress to Drag)

在触摸设备上,有时很难确定触摸是否应该滚动或拖动对象
确定意图的常用方法是时间阈值
按住元素足够长的时间,手势将转换为拖动而不是滚动
现在可以使用longpress事件上可用的新startDrag方法来实现这一点

el.on('longpress', function(e) {
    e.startDrag();
});

在使用Pointer事件时,在浏览器(IE和Edge)上,还必须对元素设置适当的触摸操作,以防止在拖动元素时浏览器滚动

el.setTouchAction({
    panX: false,
    panY: false
});

在使用Touch 事件时,在浏览器(Chrome和Safari)上,没有必要配置元素的Touch操作以防止滚动。相反,可以在拖动事件对象上调用preventDefault以防止滚动发生

el.on('drag', function(e) {
    e.preventDefault();
});

视区缩放(Viewport Zoom)

通常将以下元标记添加到html页面

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=10, user-scalable=yes"></meta>
禁用缩放(不推荐)
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
posted @ 2022-07-26 08:09  重庆熊猫  阅读(236)  评论(0编辑  收藏  举报