iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >如何进行HTML5中手势原理分析与数学知识的实践
  • 574
分享到

如何进行HTML5中手势原理分析与数学知识的实践

2024-04-02 19:04:59 574人浏览 八月长安
摘要

本篇文章为大家展示了如何进行HTML5中手势原理分析与数学知识的实践,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。引言在这触控屏的时代,人性化的手势操作已经深入了我

本篇文章为大家展示了如何进行HTML5中手势原理分析与数学知识的实践,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

引言

在这触控屏的时代,人性化的手势操作已经深入了我们生活的每个部分。现代应用越来越重视与用户的交互及体验,手势是最直接且最为有效的交互方式,一个好的手势交互,能降低用户的使用成本和流程,大大提高了用户的体验。

近期,公司的多个项目中都对手势有着较高的需求,已有的手势库无法完全cover,因此便撸了一个轻量、便于使用的移动端手势库。这篇博文主要是解析了移动端常用手势的原理,及从前端的角度学习过程中所使用的数学知识。希望能对大家有一点点的启发作用,也期待大神们指出不足甚至错误,感恩。

主要讲解项目中经常使用到的五种手势:

  • 拖动: drag

  • 双指缩放: pinch

  • 双指旋转: rotate

  • 单指缩放: singlePinch

  • 单指旋转: singleRotate

Tips :
因为 tap 及 swipe 很多基础库中包含,为了轻便,因此并没有包含,但如果需要,可进行扩展;

实现原理

众所周知,所有的手势都是基于浏览器原生事件touchstart, touchmove, touchend, touchcancel进行的上层封装,因此封装的思路是通过一个个相互独立的事件回调仓库handleBus,然后在原生touch事件中符合条件的时机触发并传出计算后的参数值,完成手势的操作。实现原理较为简单清晰,先不急,我们先来理清一些使用到的数学概念并结合代码,将数学运用到实际问题中,数学部分可能会比较枯燥,但希望大家坚持读完,相信会收益良多。

基础数学知识函数

我们常见的坐标系属于线性空间,或称向量空间(Vector Space)。这个空间是一个由点(Point) 和 向量(Vector) 所组成集合

点(Point)

可以理解为我们的坐标点,例如原点O(0,0),A(-1,2),通过原生事件对象的touches可以获取触摸点的坐标,参数index代表第几接触点;

如何进行HTML5中手势原理分析与数学知识的实践

向量(Vector)

是坐标系中一种 既有大小也有方向的线段,例如由原点O(0,0)指向点A(1,1)的箭头线段,称为向量a,则a=(1-0,1-0)=(1,1);

如下图所示,其中i与j向量称为该坐标系的单位向量,也称为基向量,我们常见的坐标系单位为1,即i=(1,0);j=(0,1);

如何进行HTML5中手势原理分析与数学知识的实践

获取向量的函数:

如何进行HTML5中手势原理分析与数学知识的实践

向量模

代表 向量的长度,记为|a|,是一个标量,只有大小,没有方向;

几何意义代表的是以x,y为直角边的直角三角形的斜边,通过勾股定理进行计算;

如何进行HTML5中手势原理分析与数学知识的实践

getLength函数:

如何进行HTML5中手势原理分析与数学知识的实践

向量的数量积

向量同样也具有可以运算的属性,它可以进行加、减、乘、数量积和向量积等运算,接下来就介绍下我们使用到的数量积这个概念,也称为点积,被定义为公式:

当a=(x1,y1),b=(x2,y2),则a·b=|a|·|b|·cosθ=x1·x2+y1·y2;

共线定理

共线,即两个向量处于 平行 的状态,当a=(x1,y1),b=(x2,y2),则存在***的一个实数λ,使得a=λb,代入坐标点后,可以得到 x1·y2= y1·x2;

因此当x1·y2-x2·y1>0 时,既斜率 ka > kb ,所以此时b向量相对于a向量是属于顺时针旋转,反之,则为逆时针;

旋转角度

通过数量积公式我们可以推到求出两个向量的夹角:

cosθ=(x1·x2+y1·y2)/(|a|·|b|);

然后通过共线定理我们可以判断出旋转的方向,函数定义为:

如何进行HTML5中手势原理分析与数学知识的实践

矩阵与变换

由于空间最本质的特征就是其可以容纳运动,因此在线性空间中,

我们用向量来刻画对象,而矩阵便是用来描述对象的运动;

而矩阵是如何描述运动的呢?

我们知道,通过一个坐标系基向量便可以确定一个向量,例如 a=(-1,2),我们通常约定的基向量是 i = (1,0) 与 j = (0,1); 因此:

a = -1i + 2j = -1(1,0) + 2(0,1) = (-1+0,0+2) = (-1,2);

而矩阵变换的,其实便是通过矩阵转换了基向量,从而完成了向量的变换;

例如上面的栗子,把a向量通过矩阵(1,2,3,0)进行变换,此时基向量i由 (1,0)变换成(1,-2)j(0,1)变换成(3,0),沿用上面的推导,则

a = -1i + 2j = -1(-1,2) + 2(3,0) = (5,-2);

如下图所示:

A图表示变换之前的坐标系,此时a=(-1,2),通过矩阵变换后,基向量i,j的变换引起了坐标系的变换,变成了下图B,因此a向量由(-1,2)变换成了(5,-2);

其实向量与坐标系的关联不变(a = -1i+2j),是基向量引起坐标系变化,然后坐标系沿用关联导致了向量的变化;

如何进行HTML5中手势原理分析与数学知识的实践

结合代码

其实CSS的transfORM等变换便是通过矩阵进行的,我们平时所写的translate/rotate等语法类似于一种封装好的语法糖,便于快捷使用,而在底层都会被转换成矩阵的形式。例如transform:translate(-30px,-30px)编译后会被转换成transform : matrix(1,0,0,1,30,30);

通常在二维坐标系中,只需要 2X2 的矩阵便足以描述所有的变换了, 但由于CSS是处于3D环境中的,因此CSS中使用的是 3X3 的矩阵,表示为:

如何进行HTML5中手势原理分析与数学知识的实践

其中第三行的0,0,1代表的就是z轴的默认参数。这个矩阵中,(a,b) 即为坐标轴的 i基,而(c,d)既为j基,e为x轴的偏移量,f为y轴的偏移量;因此上栗便很好理解,translate并没有导致i,j基改变,只是发生了偏移,因此translate(-30px,-30px) ==> matrix(1,0,0,1,30,30)~

所有的transform语句,都会发生对应的转换,如下:

// 发生偏移,但基向量不变; transform:translate(x,y) ==> transform:matrix(1,0,0,1,x,y)   // 基向量旋转; transform:rotate(θdeg)==> transform:matrix(cos(θ·π/180),sin(θ·π/180),-sin(θ·π/180),cos(θ·π/180),0,0)   // 基向量放大且方向不变; transform:scale(s) ==> transform:matrix(s,0,0,s,0,0)

translate/rotate/scale等语法十分强大,让我们的代码更为可读且方便书写,但是matrix有着更强大的转换特性,通过matrix,可以发生任何方式的变换,例如我们常见的镜像对称,transform:matrix(-1,0,0,1,0,0);

如何进行HTML5中手势原理分析与数学知识的实践

MatrixTo

然而matrix虽然强大,但可读性却不好,而且我们的写入是通过translate/rotate/scale的属性,然而通过getComputedStyle读取到的 transform却是matrix:

transform:matrix(1.41421, 1.41421, -1.41421, 1.41421, -50, -50);

请问这个元素发生了怎么样的变化?。。这就一脸懵逼了。-_-|||

因此,我们必须要有个方法,来将matrix翻译成我们更为熟悉的translate/rotate/scale方式,在理解了其原理后,我们便可以着手开始表演咯~

我们知道,前4个参数会同时受到rotatescale的影响,具有两个变量,因此需要通过前两个参数根据上面的转换方式列出两个不等式:

cos(θ·π/180)*s=1.41421;  sin(θ·π/180)*s=1.41421;

将两个不等式相除,即可以轻松求出θs了,perfect!!函数如下:

如何进行HTML5中手势原理分析与数学知识的实践

手势原理

接下来我们将上面的函数用到实际环境中,通过图示的方式来模拟手势的操作,简要地讲解手势计算的原理。希望各位大神理解这些基础的原理后,能创造出更多炫酷的手势,像我们在Mac触控板上使用的一样。

下面图例:

圆点: 代表手指的触碰点;

两个圆点之间的虚线段: 代表双指操作时组成的向量;

a向量/A点:代表在 touchstart 时获取的初始向量/初始点;

b向量/B点:代表在 touchmove 时获取的实时向量/实时点;

坐标轴底部的公式代表需要计算的值;

Drag(拖动事件)

如何进行HTML5中手势原理分析与数学知识的实践

上图是模拟了拖动手势,由A点移动到B点,我们要计算的便是这个过程的偏移量;

因此我们在touchstart中记录初始点A的坐标:

// 获取初始点A; let startPoint = getPoint(ev,0);

然后在touchmove事件中获取当前点并实时的计算出△x△y

// 实时获取初始点B; let curPoint = getPoint(ev,0);   // 通过A、B两点,实时的计算出位移增量,触发 drag 事件并传出参数; _eventFire('drag', {     delta: {         deltaX: curPoint.x - startPoint.x,         deltaY: curPoint.y - startPoint.y,     },     origin: ev, });

Tips: fire函数即遍历执行drag事件对应的回调仓库即可;

Pinch(双指缩放)

如何进行HTML5中手势原理分析与数学知识的实践

上图是双指缩放的模拟图,双指由a向量放大到b向量,通过初始状态时的a向量的模与touchmove中获取的b向量的模进行计算,便可得出缩放值:

// touchstart中计算初始双指的向量模; let vector1 = getVector(secondPoint, startPoint); let pinchStartLength = getLength(vector1);   // touchmove中计算实时的双指向量模; let vector2 = getVector(curSecPoint, curPoint); let pinchLength = getLength(vector2); this._eventFire('pinch', {     delta: {         scale: pinchLength / pinchStartLength,     },     origin: ev, });

Rotate(双指旋转)

如何进行HTML5中手势原理分析与数学知识的实践

初始时双指向量a,旋转到b向量,θ便是我们需要的值,因此只要通过我们上面构建的getAngle函数,便可求出旋转的角度:

// a向量; let vector1 = getVector(secondPoint, startPoint);   // b向量; let vector2 = getVector(curSecPoint, curPoint);   // 触发事件; this._eventFire('rotate', {     delta: {         rotate: getAngle(vector1, vector2),     },     origin: ev, });

singlePinch(单指缩放)

如何进行HTML5中手势原理分析与数学知识的实践

与上面的手势不同,单指缩放和单指旋转都需要多个特有概念:

操作元素(operator):需要操作的元素。上面三个手势其实并不关心操作元素,因为单纯靠手势自身,便能计算得出正确的参数值,而单指缩放和旋转需要依赖于操作元素的基准点(操作元素的中心点)进行计算;

按钮:因为单指的手势与拖动(drag)手势是相互冲突的,需要一种特殊的交互方式来进行区分,这里是通过特定的区域来区分,类似于一个按钮,当在按钮上操作时,是单指缩放或者旋转,而在按钮区域外,则是常规的拖动,实践证明,这是一个用户很容易接受且体验较好的操作方式;

图中由a向量单指放大到b向量,对操作元(正方形)素进行了中心放大,此时缩放值即为b向量的模 / a向量的模;

// 计算单指操作时的基准点,获取operator的中心点; let singleBasePoint = getBasePoint(operator);   // touchstart 中计算初始向量模; let pinchV1 = getVector(startPoint,singleBasePoint); singlePinchStartLength = getLength(pinchV1);   // touchmove 中计算实时向量模; pinchV2 = getVector(curPoint, singleBasePoint); singlePinchLength = getLength(pinchV2);   // 触发事件; this._eventFire('singlePinch', {     delta: {         scale: singlePinchLength / singlePinchStartLength,     },     origin: ev, });

singleRotate(单指旋转)

如何进行HTML5中手势原理分析与数学知识的实践

结合单指缩放和双指旋转,可以很简单的知道 θ便是我们需要的旋转角度;

// 获取初始向量与实时向量 let rotateV1 = getVector(startPoint, singleBasePoint); let rotateV2 = getVector(curPoint, singleBasePoint);   // 通过 getAngle 获取旋转角度并触发事件; this._eventFire('singleRotate', {     delta: {         rotate: getAngle(rotateV1, rotateV2),     },     origin: ev, });

运动增量

由于touchmove事件是个高频率的实时触发事件,一个拖动操作,其实触发了N次的touchmove事件,因此计算出来的值只是一种增量,即代表的是一次 touchmove事件增加的值,只代表一段很小的值,并不是最终的结果值,因此需要由mtouch.js外部维护一个位置数据,类似于:

//    真实位置数据; let dragTrans = {x = 0,y = 0};   // 累加上 mtouch 所传递出的增量 deltaX 与 deltaY; dragTrans.x += ev.delta.deltaX; dragTrans.y += ev.delta.deltaY;   // 通过 transform 直接操作元素; set($drag,dragTrans);

初始位置

维护外部的这个位置数据,如果初始值像上述那样直接取0,则遇到使用css设置了transform属性的元素便无法正确识别了,会导致操作元素开始时瞬间跳回(0,0)的点,因此我们需要初始去获取一个元素真实的位置值,再进行维护与操作。此时,便需要用到上面我们提到的getComputedStyle方法与matrixTo函数:

// 获取css transform属性,此时得到的是一个矩阵数据; // transform:matrix(1.41421,1.41421,-1.41421,1.41421,-50,-50); let style = window.getComputedStyle(el,null); let cssTrans = style.transform || style.WEBkitTransform;   // 按规则进行转换,得到: let initTrans = _.matrixTo(cssTrans);   // {x:-50,y:-50,scale:2,rotate:45}; // 即该元素设置了:transform:translate(-50px,-50px) scale(2) rotate(45deg);

至此,相信大家对手势的原理已经有基础的了解,基于这些原理,我们可以再封装出更多的手势,例如双击,长按,扫动,甚至更酷炫的三指、四指操作等,让应用拥有更多人性化的特质。

基于以上原理,我封装了几个常见的工具:(求star -.-)

Tips: 因为只针对移动端,需在移动设备中打开demo,或者pc端开启mobile调试模式!

  1. mtouch.js : 移动端的手势库,封装了上述的五种手势,精简的api设计,涵盖了常见的手势交互,基于此也可以很方便的进行扩展。

  2. touchkit.js : 基于mtouch所封装的一层更贴近业务的工具包,可用于制作多种手势操作业务,一键开启,一站式服务。

  3. mcanvas.js : 基于canvas 开放极简的api实现图片 一键导出等。

上述内容就是如何进行html5中手势原理分析与数学知识的实践,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网JavaScript频道。

--结束END--

本文标题: 如何进行HTML5中手势原理分析与数学知识的实践

本文链接: https://www.lsjlt.com/news/83064.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何进行HTML5中手势原理分析与数学知识的实践
    本篇文章为大家展示了如何进行HTML5中手势原理分析与数学知识的实践,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。引言在这触控屏的时代,人性化的手势操作已经深入了我...
    99+
    2024-04-02
  • 如何进行Java Mybatis中的Mapper原理分析
    如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。准备1.pom文件 <depen...
    99+
    2023-06-26
  • 如何进行单元测试利器JUnit的实践与分析
    今天就跟大家聊聊有关如何进行单元测试利器JUnit的实践与分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。单元测试工具Junit是一个开源项目,昨天学习了一下这个东西,总结下心得。...
    99+
    2023-06-17
  • MongoDB在物业管理行业中的应用实践与数据分析
    MongoDB是一种非关系型数据库管理系统,常用于处理大规模数据和高并发访问的场景。在物业管理行业中,MongoDB的应用已经取得了显著的成果。本文将探讨MongoDB在物业管理行业中的应用实践与数据分析。一、物业管理行业的挑战物业管理行业...
    99+
    2023-11-02
    数据分析 MongoDB 物业管理
  • 如何进行JDK7新特性中fork/join框架的原理分析
    如何进行JDK7新特性中fork/join框架的原理分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。原理解析:fork分解,join结合。这个框架的本质是将一个任务分解成多个...
    99+
    2023-06-17
  • 如何使用Python中的数据分析库进行数据处理
    如何使用Python中的数据分析库进行数据处理人们越来越重视数据处理和分析的重要性。随着电子设备的不断普及和互联网的发展,我们每天都会产生大量的数据。要从这些海量的数据中提取有用的信息和洞察,就需要使用强大的工具和技术。Python作为一种...
    99+
    2023-10-22
    Python 数据分析 数据处理
  • 如何使用Python中的NumPy库进行大数据分析和自然语言处理?
    Python中的NumPy库是一个开源的科学计算库,提供了高性能的多维数组对象以及用于处理这些数组的各种函数。NumPy库被广泛地应用于数据分析、机器学习、自然语言处理等领域,因为它能够处理大规模的数据集并提供高效的计算方法。 本文将介绍如...
    99+
    2023-09-13
    自然语言处理 大数据 numy
  • 如何在Python中进行数据缺失值处理和填充的最佳实践和算法选择
    如何在Python中进行数据缺失值处理和填充的最佳实践和算法选择引言数据分析中常常会遇到缺失值的情况。缺失值的存在可能会严重影响数据分析和模型训练的结果。因此,对于缺失值的处理和填充成为了数据分析的重要一环。本文将介绍在Python中进行数...
    99+
    2023-10-22
    Python 填充 关键词: 缺失值处理
  • 如何使用Python中的数据分析库和可视化工具对大规模数据进行处理和展示
    如何使用Python中的数据分析库和可视化工具对大规模数据进行处理和展示,需要具体代码示例数据分析和可视化是现代科学和商业决策的关键工具。Python是一种功能强大且易于使用的编程语言,具有丰富的数据分析库和可视化工具,如NumPy、Pan...
    99+
    2023-10-22
    可视化 Python 数据分析
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作