更新 : 2019-03-22

以前以为 hammer 的触发顺序是 parent -> child 和我们常用的 js 冒泡相反 .

今天才知道原来 hammer 根本没有冒泡或者捕获的概念,你先绑定哪一个事件它就触发哪一个. 晕 ~

hammer 还有一个看上去好像 bug 的问题

<div id="keat" class="keat">
<div id="left" class="left"></div>
<div id="right" class="right"></div>
</div>
const left = new Hammer(document.getElementById('left'));
left.on('panstart', (e: HammerInput) => console.log(e.target)); const keat = new Hammer(document.getElementById('keat'));
keat.on('panstart', (e: HammerInput) => console.log(e.target));

如果我们起始点是 left 然后 10px 后在 right, 这时 hammer 触发获取到的 e.target 会有 2 个.

left 获取到 left, keat 获取到 right

如果我们依赖 e.target 做判断要不要触发 event handler 可能就会遇到坑了.  目前没有办法解决. 我是想办法让用户避开这种交互.

更新 : 2019-03-12

double tap

var manager = new Hammer(el);
const tap = manager.get('tap');
manager.remove('tap'); var doubleTap = new Hammer.Tap({
event: 'doubletap',
taps: 2
}); manager.add([doubleTap, tap]); tap.requireFailure(doubleTap);
doubleTap.recognizeWith(tap); manager.on('doubletap', function (e) {
console.log('doubletap');
}); manager.on('tap', function (e) {
console.log('tap');
});

留意 manager.add array 的顺序, 反过来就不触发了.

double tap 和 tap 要互相认识一下. 因为彼此是有影响的.

更新 : 2018-01-31 (hammer 的坑)

hammer 的 pinch 在某种情况下会自动触发 panEnd,很奇葩.

解决方法就是记入时间呗

refer : https://github.com/hammerjs/hammer.js/issues/1134

hammer 有鬼, ghost click

如果你使用 pan + click 你会发现触发是这样的 panStart->panMove->panEnd->click

这个 browser 的行为有点不同

browser 是 mousedown -> mouseup -> click 或者 mousedown -> mousemove -> 没了

只要有 move click 事件是不会触发的.

所以这点要特别留意, 如果你不希望这个 ghost click 发生, hammer 也给出了方法

refer :

http://hammerjs.github.io/tips/

https://gist.github.com/jtangelder/361052976f044200ea17

就是在 click 时做一个判断.

另外提一个奇葩场景,如果你 bind 了 dragStart 然后 event.preventDefault 那么这个 ghostclick 是会被取消的, 但是 dragStart 是否每一次都会触发很难说 (我们看过 hammer 源码,不过我觉得它视乎动了点手脚).

更新 : 2018-01-18 

今天开发的时候遇到了一些奇葩形象.

看了看源码理清一下之前没有讲清楚的点

1. ng 有 3 个 Event Plugin (自己想扩展多几个是 ok 的), Dom Event Plugin, KeyBoard Event Plugin, HammerGesture Plugin

2. 所有的 plugin in 都必须在 app 级的 providers 去提供, lazy load 就迟了 (refer : https://github.com/angular/material2/issues/7905  and https://github.com/angular/angular/issues/19874)

3. angular material 的 MatSliderModule 会去覆盖 hammer 的 config ( 和我以前说到的方式是一样的 ) .

所以问题来了.

1. 你要 angular material 的 MatSliderModule 的手势 work good, 那么就一定要在 app 级注入这个模块, 或者提供它的手势 override 在 app providers (原因是上面第 2 条)

2. 如果你自己有一套 hammer config 逻辑, 那么注定会和 material 的 config 打架 ( 上面的 第 3 条 ), ng 只运行一个 hammer config

怎么破 ?

目前没有什么好方法. 大费周章的做法是, 开发一套 MyHammerGesture Plugin 并且把监听 (pan)="do()"  换成 (myPan)="do()"  这样就不会和它们打架咯.

material team 给出了一个方向

https://github.com/angular/material2/issues/4595

大致上就是他们以后会使用 service, 我个人觉得把 config 让出来给 app 是对的,如果我们写自己的库也应该自己封装 hammer 而不是用掉只有一个的 config.

更新 : 2017-12-28

hammer 的绑定流程是, 选择 element -> 实例化 hammer -> 设置 hammer (default 有些设置是关上的) -> 绑定监听事件.

pinch 和 rotate 设置默认是关上的, 想监听就要先打开设置, 这 2 个事件 hammer 会使用 css touch-action : none 来禁止游览器处理 touch (意思是说不能 scroll 了)

hammertime.get('pinch').set({ enable: true });
hammertime.get('rotate').set({ enable: true });

pan 和 swipe 默认设置是处理 horizontal 横向而已, 直的话是游览器的 scroll, touch-action : pan-y, 如果要监听多点就打开设置

hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });

以上是 hammer 的基本处理思路, 默认情况下让游览器可以 scroll. 要处理更多就自己设置吧.

ng 方面. 之前(看下面) 有提到过了. 所有的手势 ng 都会开启 hammer 的 pinch 和 rotate 设置, 也就是说即使你只是写了一个 (tap) 事件, 你的 element 就不能 scroll 了.

为什么 ng 要这样呢, 我也不知道. 可能懒得去理会吧. 全部开启设置, 才能统一方式绑定 (pinch) 和 (rotate) 嘛.

一直没有好的解决方法 ng 没什么接口方便我们覆盖这个逻辑

refer : https://medium.com/@TheLarkInn/creating-custom-dom-events-in-angular2-f326d348dc8b  (ng 自定义事件绑定)

ng 的 dom event 源码

https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/dom_events.ts

https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/event_manager.ts

https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/hammer_gestures.ts

https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/events/key_events.ts

几个方法参考 :

1. 直接调用 Hammer 不用 ng 的绑定

2. 覆盖 HammerGestureConfig.buildHammer 方法, 这个方法只能获取到 element, 所以我们通过在 element 上面写 data-need-rotate or data-need-pinch 之类的表达, 来实现不同情况下不同的 hammer 设置

3. 覆盖 HammerGesturesPlugin 来个统统重写...

我目前用了第 2 个 方案. 暂时挺着吧.

更新 22-08-2017

hammerjs 的事件有不同的设置 options

var myElement = document.getElementById('myElement');
var mc = new Hammer(myElement);
mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });
mc.on("panleft panright panup pandown tap press", function(ev) {
myElement.textContent = ev.type +" gesture detected.";
});

pan 事件默认的 direction 是没有包含上下移动的, 那我们可以自己去设置它.

而 Angular 默认会帮我们把所有的 hammer 都设置一遍如下的代码

这 2 个设置会让所有的 hammer element 无法滚动. 这个要注意哦.

我们可以通过 overrides 去添加和覆盖上面的逻辑.

  providers: [{
provide: HAMMER_GESTURE_CONFIG,
useClass: MyHammerConfig
}] export class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{
'pan': { direction : Hammer.DIRECTION_ALL }
}
}

大概这样就可以了,不过呢这个 config 是全局的. 目前我还没发放可以针对不同的 element 设置不同的 config .

可能需要直接调用 hammerjs 才可以了。

refer :

http://hammerjs.github.io/

https://bevacqua.github.io/dragula/

手机 和 PC 在交互体验上最大的区别是交互工具不同.

PC端,我们用滑鼠

手机端, 我们用触屏

滑鼠 vs 触屏

滑鼠有 hover 概念, 触屏没有.

触屏能多点 (多种手势), 滑鼠没有.

responsive design 解决了视觉上的差异问题,却没有解决交互上的差异问题.

hammerjs 帮我们解决的是滑鼠, 触屏之前的差异问题.

比如 : 监听各种手势, click 的 delay 300ms 问题, touchmove 模拟成 mousemove 事件等等.

angular 认可 hammerjs, 所以只要你 import hammerjs, 你可以直接这样写

<div (tap)="test()" >
test
</div>

angular 会使用 hammerjs 的方法来绑定 tap 事件. 很方便吧 ?

使用 npm 加载

  "dependencies": {
"hammer-timejs": "^1.1.0",
"hammer-touchemulator": "0.0.2",
"hammerjs": "^2.0.8",
},
"devDependencies": {
"@types/hammerjs": "^2.0.34",
}

在 main.ts 里 import 就可以啦

import 'hammerjs';
import 'hammer-timejs';
import * as TouchEmulator from 'hammer-touchemulator';
TouchEmulator();

TouchEmulator 是 development 情况下的才使用的.

手机还有一个问题就是在 drag and drop. 原生游览器的 drag and drop 在手机端支持的不好.

很多人会用 touchmove 来模拟. 也就是 hammerjs 里面的 pan 事件.

但是具体做法还是挺困难的.

因为触屏没有 hover 概念, 也没 touchover 事件, 所以当用户 pan 的时候你并没有办法轻易的监听 dragover 来处理事情. (比如你要做 sorting)

我在网上看了一些人的做法是通过 document.elementFromPoint(x,y) 来获取交会的节点或则每一次 pan 的时候都通过 service 发布事件, 然后其它组件监听, 在依据自己的 element.getBoundingClientRect 的

position 来确定是否 over 到了 element. 简单就说就是模拟 dragover 事件.

如果你有好方法欢迎你留意告诉我哦.

angular2 学习笔记 の 移动端开发 ( 手势 )的更多相关文章

  1. Qlik Sense学习笔记之Mashup开发(二)

    date: 2019-01-26 11:28:07 updated: 2019-01-26 11:28:07 Qlik Sense学习笔记之Mashup开发(二) 1.Mobile SPA UI Fr ...

  2. Qlik Sense学习笔记之Mashup开发(一)

    date: 2018-12-21 12:33:29 updated: 2018-12-21 12:33:29 Qlik Sense学习笔记之Mashup开发(一) 1.基于Qlik Sense API ...

  3. Android(java)学习笔记219:开发一个多界面的应用程序之两种意图

    1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...

  4. APPCAN学习笔记003---原生开发与HTML5技术

    APPCAN学习笔记003---原生开发与HTML5技术 技术qq交流群:JavaDream:251572072 1.HTML5的优势:   HTML5强悍牢固的骨架   CSS3精致到每一个毛孔的皮 ...

  5. APPCAN学习笔记001---app高速开发AppCan.cn平台概述

    1.APPCAN学习笔记---app高速开发AppCan.cn平台概述 1. 平台概述 技术qq交流群:JavaDream:251572072 AppCan.cn开发平台是基于HTML5技术的跨平台移 ...

  6. Hadoop学习笔记(4) ——搭建开发环境及编写Hello World

    Hadoop学习笔记(4) ——搭建开发环境及编写Hello World 整个Hadoop是基于Java开发的,所以要开发Hadoop相应的程序就得用JAVA.在linux下开发JAVA还数eclip ...

  7. Android(java)学习笔记162:开发一个多界面的应用程序之两种意图

    1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...

  8. jsp学习笔记:mvc开发模式

    jsp学习笔记:mvc开发模式2017-10-12 22:17:33 model(javabe)与view层交互 view(视图层,html.jsp) controller(控制层,处理用户提交的信息 ...

  9. angular2 学习笔记 ( server-side rendering, angular universal, 服务端渲染 )

    更新 : 2018-01-10  大半年过去了依然没有做 server side render 的冲动,但是一直有关注这方便的做法. 今天领悟了一些道理, 这里做个记入. server side re ...

随机推荐

  1. mysql 服务启动失败

    mysql 数据库连接失败 1.用naviCat Preiumn 连接本地的mysql 失败,查找原因,mysql 数据库服务没有启用,但是在服务列表里面没有找到对应的mysql 服务. 所以在cmd ...

  2. Eclipse中JRE(unbound)问题的一种解决方法

    (如果有写的不对的地方,欢迎指正!) 1.检查Java环境变量配置是否有问题 jdk1.8环境变量配置(1.8和8是一个意思) jdk9环境变量配置 注:配置不成功的一种可能是安装多个jdk,解决方法 ...

  3. shell中的数字

    shell中的数字 author :headsen chen date :2017-10-18  15:01:42 个人原创,转载请注明作者,出处,否则依法追究法律责任 1,生成随机数(范围:0-32 ...

  4. git 菜鸟入门

    1. 推荐的 git 仓库(注册帐号并登录): https://github.com/ https://git.oschina.net/2. 创建仓库       里面的地址为 git 仓库的地址 , ...

  5. VMware 滴滴声解决

    去除虚拟机tab时的滴滴声 # cat /etc/inputrc Set bell-style none 重启生效

  6. MSF添加ms17-010的exp脚本及攻击复现

    原文地址:https://bbs.ichunqiu.com/thread-23115-1-1.html 本来今晚在准备复现最近的CVE-2017-11882,由于本人是小白一枚,不知道这么添加msf的 ...

  7. 【Python】 汉字转化汉语拼音pinyin

    pinyin pinyin模块是github上一个小项目,在github.com/cleverdeng/pinyin.py上面可以下到源码.衷心感谢那些为这个模块做出贡献的人来方便我们[鞠躬] 安装: ...

  8. LAMP平台部署(转)

    LAMP平台的概述 LAMP环境脚本部署:https://github.com/spdir/ShellScripts/tree/master/lamp LAMP的介绍:百度百科 LAMP平台的构成组件 ...

  9. Python基础-week05

    本节大纲:Author:http://www.cnblogs.com/Jame-mei 模块介绍 time & datetime模块 random os sys shutil json &am ...

  10. codeforce round #467(div.2)

    A. Olympiad 给出n个数,让你找出有几个非零并且不重复的数 所以用stl的set //#define debug #include<stdio.h> #include<ma ...