/any-touch

:wave: 手势库, 2kb~5kb, 支持PC / 手机 / 微信端.

Primary LanguageTypeScriptMIT LicenseMIT

any-touch NPM Version NPM Downloads size-image codecov CircleCI

👋 一个小巧的手势库.

  • 更多端: PC 端 / 移动端 / 微信小程序.
  • 更全面: 支持Tap(点击) / Press(按压) / Pan(拖拽) / Swipe(快划) / Pinch(缩放) / Rotate(旋转)6种手势.
  • 更灵巧: 默认加载6个手势, 也可🤖按需加载手势, 核心@any-touch/core只有2kb, 完整安装也仅需要5kb.
  • 更简单: 在Vue可直接通过v-on调用, 比如<div @pan="onPan"></div>.
  • 更放心: 代码测试覆盖率100%.

演示

查看二维码

直接访问

目录

⚡ 快速开始

🌱 兼容vue语法

📱 支持微信小程序

🤖 按需加载

💡 API

🍭 事件对象(event)

❗❗❗ 注意事项

安装

npm i -S any-touch

CDN

https://unpkg.com/any-touch/dist/any-touch.min.js

快速开始

import AnyTouch from 'any-touch';
const el = doucument.getElementById('box');
const at = new AnyTouch(el);
// 单击
at.on('tap', (ev) => {
    // ev包含位置/速度/方向等信息
});

返回目录

兼容vue语法

<div 
    @tap="onTap" 
    @swipe="onSwipe" 
    @press="onPress" 
    @pan="onPan" 
    @pinch="onPinch" 
    @rotate="onRotate">
    <p>Hello any-touch</p>
</div>
import AnyTouch from 'any-touch';
export default {
    mounted() {
        // 没错, 就这2行
        const {destroy} = new AnyTouch(this.$el);
        this.on('hook:destroy', destroy);
    }
};

注意

  1. 默认any-touch 会模拟原生 dom 事件触发, 所以在 vue 上可以通过 v-on 直接绑定手势, 如不需要可通过new AnyTouch(el, {domEvents:false}关闭.

  2. 由于框架(vue等)的特殊行, 建议多触点手势(pinch/rotate等pointLength>1的手势)使用match, 如<div @pinch="$event.match() && onPinch"></div>, 用来保证每个触点都落在目标元素内(使用anyTouch.target().on()监听不需要考虑这个问题.

返回目录

支持微信小程序

由于微信小程序中没有 dom 元素的概念, 所以我们需要通过catchEvent方法手动接收 touch 事件的事件对象来进行识别!

<view 
  @touchstart="onTouchstart"
  @touchmove="onTouchmove"
  @touchend="onTouchend"></view>
const at = new AnyTouch()
{
    onload(){
        at.on('press', ev=>{
            // 按压
        });
    },

    methods: {
      onTouchstart(ev){
        at.catchEvent(ev);
      },
      onTouchmove(ev){
        at.catchEvent(ev);
      },
      onTouchend(ev){
        at.catchEvent(ev);
      }
    }
}

返回目录

target(事件委派)

如果有多个元素需要绑定手势, 那么建议初始化绑定一个父元素, 通过target绑定子元素和函数.

const at =  new AnyTouch(parent);
at.on('pan', onPan, { target: child });
// 还可以表示为
at.target(child).on('pan', onPan);

返回目录

beforeEach(触发拦截)

手势的触发与否可自由控制, 比如可以实现"单击延迟300ms, 如果双击没有触发才触发(默认手势事件都是并行触发)":

import AnyTouch from '@any-touch/core';
import Tap from '@any-touch/tap';
import {STATUS_POSSIBLE, STATUS_FAILED} from '@any-touch/shared';
import debounce from 'lodash/debounce'
AnyTouch.use(Tap);
AnyTouch.use(Tap, { name: 'doubletap', tapTimes: 2 });
const at = new AnyTouch(el);

// 🚀关键代码
// beforeEach
at.beforeEach(({ recognizerMap, name }, next) => {
    if ('tap' === name) {
        debounce(() => {
            if ([STATUS_POSSIBLE, STATUS_FAILED].includes(recognizerMap.doubletap.status)) next();
        }, 300);
    } else {
        next();
    }
});

at.on('tap', onTap);
at.on('doubletap', onDoubleTap);

"next"的执行用来决定是否触发对应事件. 说道这里顺便解释下手势识别器的状态:

手势识别器的状态

变量 说明
STATUS_POSSIBLE 表示当前还"未识别"
STATUS_START "拖拽类"手势(pan/pinch/rotate等)中表示"第一次识别."
STATUS_MOVE "拖拽类"手势中表示"识别后移动中"
STATUS_END "拖拽类"手势中表示"有触点离开,即手势结束"
STATUS_CANCELLED 手势识别后,发生事件中断,比如"来电话","浏览器最小化"等.
STATUS_FAILED 表示"识别失败", 比如识别tap的时候,触点在250ms内没有离开屏幕等
STATUS_RECOGNIZED 表示"已识别", 区别于"拖拽类"手势, 用在"瞬发"识别的手势,比如tap/press/swipe.

按需加载

默认any-touch支持所有手势, 为了减小"体积"和"不必要的识别器执行时间", 提供了按需加载.

使用"按需加载"

⚠️ 注意: 执行npm i any-touch后, "@any-touch/core"和"@any-touch/xx手势"🤖便已自动安装, 直接引入即可.

// 只加载pan识别器(拖拽)
import Core from '@any-touch/core';
import Pan from '@any-touch/pan';
// 使用Pan
Core.use(Pan);
const at = new Core(el);
// 拖拽
at.on('pan', (ev) => {
    // ev包含位置/速度/方向等信息
});

@any-touch/core

手势库的核心组件, 主要用来把Mouse/Touch输入变成统一的输出, 实现PC/Mobile端的兼容, 提供了"at:"开头的兼容事件.

import Core from '@any-touch/core';
const at = new Core(el);
// 兼容Mouse/Touch
at.on('at:touch', (ev) => {
    // ev包含位置/时间/事件对象等属性.
});
// start / move / end / cancel
at.on('at:touchstart', onStart);
at.on('at:touchmove', onMove);
at.on('at:touchend', onEnd);
at.on('at:touchcancel', onCancel);

@any-touch/xx手势

手势识别器均已做成独立的包, 从而实现按需加载.

名称 说明
@any-touch/tap 点击
@any-touch/pan 拖拽
@any-touch/swipe
@any-touch/press 按压
@any-touch/pinch 缩放
@any-touch/rotate 旋转

⚠️ 再次提示: 如果已安装"any-touch", 上面的包便也已经自动安装.

返回目录

注意事项

不要用 alert 调试

❗❗❗ 在安卓手机的真机上, 如果touchstarttouchmove阶段触发了alert, 会出现后续的touchmove/touchend不触发的 bug. 所以请大家务必避免在手势的事件回调中使用alert. 测试代码

如果仅仅是了在移动端调试, 请使用腾讯的vconsole

mac os上的chrome浏览器触发touchend会比较慢

由于上述原因, swipe事件发生的会"慢半拍",所以请大家最终测试以手机效果为准.

返回目录