热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Vue多点触控手势:移动端多指操作详解

在移动端开发中,多点触控手势是提升用户体验的重要手段。然而,目前只有iOS浏览器原生支持手势事件,其他设备需要通过touchstart、touchmove和touchend等基础事件进行自定义实现。本文将详细介绍如何在Vue项目中实现多点触控手势。

在移动端开发中,多点触控手势是提升用户体验的关键。然而,目前只有iOS浏览器原生支持手势事件,其他设备需要通过touchstart、touchmove和touchend等基础事件进行自定义实现。本文将详细介绍如何在Vue项目中实现多点触控手势。

基础触摸事件

移动端的基础触摸事件包括:

  • touchstart:触摸开始
  • touchmove:触摸移动
  • touchend:触摸结束
  • touchcancel:触摸中断(如弹框打断)

示例代码:

box.addEventListener('touchmove', function(event) {
  console.log('触摸移动');
});

touchEvent 对象

touchEvent 对象包含以下属性:

  • touches:触发事件时屏幕上的触点个数
  • targetTouches:触发事件时事件元素上的触点个数
  • changedTouches:触发事件发生改变的触点个数
  • target:事件元素
  • stopPropagation():阻止事件冒泡
  • preventDefault():阻止默认行为

示例代码:

box.addEventListener('touchstart', function(event) {
  console.log(event.touches); // 一个手指触摸时输出 Touchlist{0: Touch, length: 1}
  var startX = event.touches[0].clientX; // 触点在视口上的位置
});

手势事件

iOS 的手势事件包括:

  • gesturestart:手势开始,屏幕上有两个或两个以上的手指
  • gesturechange:手势变化,屏幕上有两个或两个以上的手指位置在移动
  • gestureend:手势结束,屏幕上只剩下少于两个手指

新增的属性包括:

  • scale:触点的距离与初始距离的比例
  • rotation:触点的角度差与初始角度差的差

示例代码:

box.addEventListener('gesturechange', function(event) {
  box.innerHTML = 'rotation: ' + event.rotation + '
'; box.innerHTML += 'scale: ' + event.scale + '
'; });

自定义多点触控手势

为了在非iOS设备上实现多点触控手势,我们可以封装一个手势插件。以下是gestrue.js的实现:

(function(w) {
  /**
   * 用于给元素监听手势事件
   * @param node 要监听的元素
   * @param callback 对象,对象有三个函数 start、change、end
   */
  function gesture(node, callback) {
    // 手势开始
    node.addEventListener('touchstart', function(event) {
      if (event.touches.length >= 2) {
        node.isGestureStart = true;
        this.startDst = getDst(event.touches[0], event.touches[1]);
        this.startDeg = getDeg(event.touches[0], event.touches[1]);
        if (callback && typeof(callback['start']) === 'function') {
          callback['start']();
        }
      }
    });

    // 手势移动
    node.addEventListener('touchmove', function(event) {
      if (event.touches.length >= 2) {
        var currentDst = getDst(event.touches[0], event.touches[1]);
        var currentDeg = getDeg(event.touches[0], event.touches[1]);
        event.scale = currentDst / this.startDst;
        event.rotation = currentDeg - this.startDeg;
        if (callback && typeof(callback['change']) === 'function') {
          callback['change'](event);
        }
      }
    });

    // 手势结束
    node.addEventListener('touchend', function(event) {
      if (node.isGestureStart && event.touches.length <2) {
        node.isGestureStart = false;
        if (callback && typeof(callback['end']) === 'function') {
          callback['end']();
        }
      }
    });

    function getDst(touch1, touch2) {
      var x = touch2.clientX - touch1.clientX;
      var y = touch2.clientY - touch1.clientY;
      var z = Math.sqrt(x * x + y * y);
      return z;
    }

    function getDeg(touch1, touch2) {
      var x = touch2.clientX - touch1.clientX;
      var y = touch2.clientY - touch1.clientY;
      var angle = Math.atan2(y, x);
      var deg = angle / Math.PI * 180;
      return deg;
    }
  }

  w.gesture = gesture;
})(window);

使用案例:实现元素缩放及旋转

以下是一个简单的示例,展示如何使用上述手势插件实现元素的缩放和旋转。

* {
  margin: 0;
  padding: 0;
}
html, body, #app {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#box {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  width: 150px;
  height: 150px;
  background-color: #f90;
}
(function() {
  var app = document.querySelector('#app');
  var box = document.querySelector('#box');

  app.addEventListener('touchstart', function(event) {
    event.preventDefault();
  });

  gesture(box, {
    start: function() {
      box.startScale = transformCss(box, 'scale') || 1;
      box.startRotate = transformCss(box, 'rotate') || 0;
    },
    change: function(event) {
      transformCss(box, 'scale', box.startScale * event.scale);
      transformCss(box, 'rotate', box.startRotate + event.rotation);
    }
  });
})();

注:本文中的transformCss函数用于设置CSS变换属性,具体实现请参考相关文档。

作者:捕猹少年闰土

若有任何问题或建议,请联系我,共同学习进步。


推荐阅读
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • CentOS 7.2 配置防火墙端口开放
    本文介绍如何在 CentOS 7.2 系统上配置防火墙以开放特定的服务端口,包括 FTP 服务的临时与永久开放方法,以及如何验证配置是否生效。 ... [详细]
  • 本文详细介绍了ActivityManagerService (AMS) 的工作原理及其在Android系统中的重要角色。AMS作为system_server进程的一部分,在系统启动时加载,负责管理和协调应用程序中的Activity和服务(Service)。文章将通过具体的接口图和通信流程,帮助读者更好地理解AMS的工作机制。 ... [详细]
  • 本文探讨了天才与疯子之间的微妙界限,介绍了如何利用巨人的工具提升自我,以及如何通过科学决策、数据洞察和智慧的尺度来指导我们的生活和工作。 ... [详细]
  • 深入理解小程序中的Picker组件
    Picker组件是一种从屏幕底部弹出的滚动选择器,支持多种选择模式,包括普通选择器、多列选择器、时间选择器、日期选择器和省市区选择器。本文将详细介绍Picker的各种属性及其应用场景。 ... [详细]
  • 本题要求计算给定两个正整数a和b时,2的-a次方与2的-b次方之和,并将结果以最简分数形式表示。输入包括多组测试数据,每组数据包含两个在2到20范围内的整数。 ... [详细]
  • 本文详细介绍了Java集合框架中的Collection体系,包括集合的基本概念及其与数组的区别。同时,深入探讨了Comparable和Comparator接口的区别,并分析了各种集合类的底层数据结构。最后,提供了如何根据需求选择合适的集合类的指导。 ... [详细]
  • YB02 防水车载GPS追踪器
    YB02防水车载GPS追踪器由Yuebiz科技有限公司设计生产,适用于车辆防盗、车队管理和实时追踪等多种场合。 ... [详细]
  • Java与JSON互转:实现JSON到Java对象及Java对象到JSON的转换
    本文详细介绍了如何在Java中实现JSON数据与Java对象之间的相互转换,包括代码示例和常见问题解决方法。 ... [详细]
  • 本文探讨了如何利用SqlDependency执行复杂的SQL查询,并确保在多线程环境下的安全性与效率。 ... [详细]
  • 本文深入探讨 PHPCMS 平台中的字符串截取函数 str_cut 的使用方法,该函数常用于控制输出的标题或内容摘要长度,有效避免因过长的文本导致的页面布局问题。通过本文,读者将掌握如何灵活运用此函数,包括处理 HTML 标签等高级技巧。 ... [详细]
  • 本文介绍了如何使用JavaScript和jQuery实现页面元素随着滚动条的移动而相应变化位置的功能,提供了一段简洁的代码示例。 ... [详细]
  • iTOP4412开发板QtE5.7源码编译指南
    本文详细介绍了如何在iTOP4412开发板上编译QtE5.7源码,包括所需文件的位置、编译器设置、触摸库编译以及QtE5.7的完整编译流程。 ... [详细]
  • 无论是初学者还是经验丰富的开发者,W3CSchool都是一个不可或缺的资源库。本文将介绍几个关键的学习资源,帮助您提升网页开发技能。 ... [详细]
  • NameNode内存优化基于缓存相同文件名的方法
    NameNode内存优化基于缓存相同文件名的方法Namenodeheapoptimizationreuseobjectsforcommonlyuse ... [详细]
author-avatar
月星名店_882
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有