移动端交互手势详解及实现

一丶概述  
    如今移动端设备大行其道,前端也走进了移动的领域。在写移动端页面的交互效果的时候,我么难免要接触一些复杂的手势,而不仅仅像pc端那样简单的鼠标事件。手势实际上是一种输入模式。我们现在在直观意义上理解的人机交互是指人与机器之间的互动方式,这种互动方式经历了鼠标、物理硬件、屏幕触控、远距离的体感操作的逐步发展的过程。

二丶移动端手势事件  
    在浏览器中,为我们提供的手势并不算多,主要有:

  1. touchstart 当手指触摸屏幕时触发
  2. touchmove 当手指在屏幕滑动时不断的触发
  3. touchend 当手指从屏幕上移开时触发
  4. touchcancel 当系统停止跟踪触摸时触发

是不是感觉很少,safari还为我们提供了三个独有的手势事件(用于复杂的手势),然而也仅仅只能在safari中使用

  1. gesturestart 当一个手指已经按在屏幕上,另一个手指也按上时触发
  2. gesturechange 当触摸屏幕上任何一个手指发生变化时触发
  3. gestureend 当任何一个手指从屏幕上移开时触发

  
    最后呢,让我们看看移动设备上究竟有哪儿手势需要我们使用  

三丶让JS支持这些手势  
    目前看来,我们能用的也就只有touchstart,touchmove, touchend, touchcancel这四个手势,那么如何才能利用这四个手势支持众多的交互效果呢?首先我们从最简单的手势开始。简单的手势也就是说是单点触控,我们主要来实现如下几个手势:

  1. tap 轻触
  2. doubletap 连续两次轻触
  3. press 长按
  4. pan 平移
  5. flick 轻拂

首先我们要解决如何触发自定义事件(已经了解自定事件的可以跳过):

//自定义一个事件
document.body.addEventListener("tap", function(event) {
console.log("tap事件触发")
}, false)
//触发自定义事件
function fireEvent(element, type, extra) {
var event = doc.createEvent(‘HTMLEvents‘);
event.initEvent(type, true, true);
if (typeof extra === ‘object‘) {
Util.extends(event, extra); //浅拷贝
}
element.dispatchEvent(event);
}
fireEvent(document.body, "tap", {}); //触发tap事件

我们在整个事件模拟中定义一个中间状态 evet.status 来表示当前的触摸状态,接下来我们就利用touchstart,touchmove,touchend来可以实现自己的触摸事件了   
    tap事件:当touchstart触发时,我们将event.status状态改为 tapping。在touchend触发时,如果event.status依然为tapping则,触发tap事件。  
    doubletap事件:在触发tap事件的时候,我们用一个变量lastTime记录当前时间。下一次触发tap时,用当前时间和lastTime做对比,如果小于300ms则触发doubletap事件  
    pess事件:当touchstart触发时,我们定义一个setTimeout的函数(500ms),如果500ms后仍然没有touchend触发,则定时函数将event.staus状态改为pressing。当touchend触发时,检测到状态为pressing则触发press事件。  
    pan事件:我们在touchmove中检测当前状态是tapping和pressing时,并且手指移动距离大于10px则,触发pan平移事件。这个移动距离用event.touches[0].clientX - lastTouch.clientY 来检测就好(利用lastTouch记录,起始手指的event对象)。  
    flick事件:这个事件就是"刷~刷"的划过屏幕的交互效果,在touchend时通过pan事件的移动距离和移动事件算出速度(注意是X和Y轴的合速度),如果速度大于0.5,并且整个触摸过程时间小于100ms,则触发flick事件。  
     是不是很简单的用最原始的浏览器事件就能实现这些内容。  
     接下来让我们看看两个手指的事件如果实现。

四丶实现多指触控 
    在实现多指触控的时候,我们需要了解一下触摸过程中event用来保存多个手指信息的三个属性:

  1. touches当前屏幕上所有触摸点的集合列表
  2. targetTouches绑定事件的那个结点上的触摸点的集合列表
  3. changedTouches触发事件时改变的触摸点的集合

这三个有什么区别?举例来说,比如div1, div2只有div2绑定了touchstart事件,第一次放下一个手指在div2上,触发了touchstart事件,这个时候,三个集合的内容是一样的,都包含这个手指的touch,然后,再放下两个手指一个在div1上,一个在div2上,这个时候又会触发事件,但changedTouches里面只包含第二个第三个手指的信息,因为第一个没有发生变化,而targetTouches包含的是在第一个手指和第三个在div2上的手指集合,touches包含屏幕上所有手指的信息,也就是三个手指。这样是不是就很很清楚了。下面我们要根据上面的内容,继续解决一个问题:当两个手指作用在不同的节点上应该触发哪个节点的事件呢?
    这里我们规定,如果触发在了两个不同节点上,我们去两个节点公有的最近父节点,作为触发的目标。寻找共有最小父节点代码如下:

//判断节点ele1是否包含ele2
function contains(ele1, ele2) {
return ele1.contains ? ele1 != ele2 && ele1.contains(ele2) : !!(ele1.compareDocumentPosition(ele2) & 16);
}
//获得共有最近的父节点
function getCommonRootNode(ele1, ele2) {
while (ele1) {
if (contains(ele1, ele2) || ele1 === ele2) {
return ele1;
}
ele1 = ele1.parentNode;
}
return null;
}

这样我们解决了,如何找到多个手指信息和触发哪个节点的问题。最后一个问题,当给了我们这些信息我们怎么能用?比如计算旋转手势,缩放手势啊什么的。  
    这里我们仅考虑两个手指的多点触控。我们设touchstart阶段的两个手指坐标为 A(x1, y1)   B(x2, y2)。touchmove过程中的两个手指的坐标为 C(x3, y3) D(x4, y4)。
    rotate旋转:计算AB,CD线段与坐标轴的夹角,对角度相减即得到旋转角度。  
    scale 缩放:计算AB线段长度和CD线段长度(勾股定理),两条线段做比值就好。  
    translate平移: 平移的话我们只计算A点到C点的x坐标变化量。 
    具体代码如下:

function calcAction(x1, y1, x2, y2, x3, y3, x4, y4) {
let rotate = Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y2 - y1, x2 - x1),
scale = Math.sqrt((Math.pow(y4 - y3, 2) + Math.pow(x4 - x3, 2)) / (Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2))),
translate = [x3 - scale * x1 * Math.cos(rotate) + scale * y1 * Math.sin(rotate), y3 - scale * y1 * Math.cos(rotate) - scale * x1 * Math.sin(rotate)];
return {
rotate: rotate,
scale: scale,
translate: translate,
/**
* |ax + cy + e|
* |bx + dy + f|
* | 0 + 0 + 1|
*/
martrix: [
[scale * Math.cos(rotate), -scale * Math.sin(rotate), translate[0]],
[scale * Math.sin(rotate), scale * Math.cos(rotate), translate[1]],
[0, 0, 1]
]
}
}

了解这些内容,你就可以在touchmove过程中完成对两个手指的旋转缩放平移等交互效果进行封装了。是不是很简单呢!  
     当然完整的事件过程要分start,move,end这三种情况,在实现的时候要分别给予对应的实现就可以了。都逃不开对touchstart,touchmove,touchend的利用。  
五丶实现案例
    基于上面的方案,我实现了一个对移动端手势的封装库,包含以上所有的手势。犹豫这里代码运行不能模拟手机环境,我就不贴代码了。  
    感兴趣的同学可以访问:https://github.com/T-phantom/si-gesture  上面有具体的使用方法和带有详细注释的源码哦,欢迎start。

时间: 2024-12-22 21:13:46

移动端交互手势详解及实现的相关文章

49.Python使用requests包进行HTTP交互方法详解

简介 使用方法 传递QUERY参数 定制请求头 填写cookie 填充请求体 处理响应对象 重定向与访问历史 超时 Session对象 根据响应获取请求 SSL认证 HTTP认证 基本认证 摘要认证 代理场景 HTTPHTTPS代理 SOCKS代理 简介 Python的HTTP包有urllib.urllib2.httplib等,但是都需要了解较多的HTTP原理才能编码,借助requests包可以在较高的抽象层次上完成HTTP交互过程的开发.安装requests使用pip install requ

IOS 七种手势详解(动图+Demo下载)

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的博客专栏,这个关于IOS SDK的专栏我会持续更新 IOS SDK详解 前言: 触摸是交互的核心,而手势是触摸的上层封装,易于使用,不易出错.本文介绍了7种常用手势,多数手势我都配合Core Animation举了一个例子.给读者一些参考.最后,Demo的链接我会放到最后. Demo源代码下载 CSDN下载 GitHub下载 一 UIGestureRecognizer UIGestureRecognizer

IOS 手势详解

在IOS中手势可以让用户有很好的体验,因此我们有必要去了解一下手势. (在设置手势是有很多值得注意的地方) *是需要设置为Yes的点击无法响应* *要把手势添加到所需点击的View,否则无法响应* 手势共有六种,下面我会分开介绍. 点击手势 // // ViewController.m // CX-手势详解 // // Created by ma c on 16/3/24. // Copyright © 2016年 xubaoaichiyu. All rights reserved. // #i

(转)Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解

这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结果,被移除首页了!前面第一篇的内容是这篇的基础,前面那些不弄好,下面的商品信息你是请求不到的,这点需要大家特别注意...有需要前面提到的内容的孩子可以点击链接进去自己看看!! 这篇就具体的总结我们Lua和OC交互的内容以及内购具体的代码以及结果的测试说明: 内购部分OC的代码实现 先自己总结一下整个

微信支付——调用微信客户端支付之【服务端】开发详解

原文:http://blog.csdn.net/seven_cm/article/details/41559301 http://blog.csdn.net/seven_cm/article/details/50019927 2015-09-12 更新: 因微信支付已经升级到V3版本,请大家参考官网的帮助文档. https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=1_2 之前一篇提到微信支付的开发过程,写得有点乱,现在重新整理一下. 好了

C++ STL 双端队列deque详解

一.解释 Deque(双端队列)是一种具有队列和栈的性质的数据结构.双端队列的元素可以从两端弹出,其限定插入和删除操作在表的两端进行. 二.常用操作: 1.头文件 #include <deque> 2.定义 a) deque<int>s1; b) deque<string>s2; c) deque<node>s3; /*node为结构体,可自行定义.*/ 3.常用操作 //a) 构造函数 deque<int> ideq //b)增加函数 ideq

IOS中的手势详解

1.点击 UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)]; //设置当前需要点击的次数 [tap setNumberOfTapsRequired:1]; //设置当前需要触发事件的手指数量 [tap setNumberOfTouchesRequired:2]; //设置当前代理 tap.delegate=self; [_view add

android——GestureDetector.OnGestureListener 手势详解

Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等.这些Gesture会使用户体验大大提升.Android中的 Gesture识别(detector)是通过GestureDetector.OnGestureListener接口实现的. 首先,Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现: 其次,所有View的子类都可以

Shell编程之Expect免交互语句详解

Expect概述 Expect是建立在tcl基础_上的一个工具,Expect 是用来进行自动化控制和测试的工具.主要解决shell脚本中不可交互的问题.对于大规模的linux运维很有帮助.在linux运维和开发中,我们经常需要远程登录服务器进行操作,登录的过程是一个交互的过程,可能会需要输入(yes/no)password等信息.为了模拟这种输入,可以使用Expect脚本. Expect安装 yum install expect -y 基本命令 send: 向进程发送字符串,用于模拟用户的输入.