热门标签 | 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变换属性,具体实现请参考相关文档。

作者:捕猹少年闰土

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


推荐阅读
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 本文详细介绍了如何解决Uploadify插件在Internet Explorer(IE)9和10版本中遇到的点击失效及JQuery运行时错误问题。通过修改相关JavaScript代码,确保上传功能在不同浏览器环境中的一致性和稳定性。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍如何在VSCode中配置自定义代码片段,使其具备与IDEA相似的代码生成快捷键功能。通过具体的Java和HTML代码片段示例,展示配置步骤及效果。 ... [详细]
  • 本文详细介绍 Go+ 编程语言中的上下文处理机制,涵盖其基本概念、关键方法及应用场景。Go+ 是一门结合了 Go 的高效工程开发特性和 Python 数据科学功能的编程语言。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 精选30本C# ASP.NET SQL中文PDF电子书合集
    欢迎订阅我们的技术博客,获取更多关于C#、ASP.NET和SQL的最新资讯和资源。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • C# LiNQ 查询 join连接
    C# LiNQ 查询 join连接 ... [详细]
  • 深入解析 Vue 的 Transition 组件与第三方动画库的结合使用
    本文详细介绍了 Vue 中的 Transition 组件,探讨其内置类名机制、触发时机及自定义类名的应用。同时,结合 animate.css 和 GSAP 等第三方库,展示了如何实现复杂的动画效果。 ... [详细]
  • 本文详细介绍了JavaScript中数组的两个重要高阶函数:map()和reduce()。map()用于将数组中的每个元素通过指定的函数进行处理并返回一个新的数组,而reduce()则用于对数组中的元素进行累积计算,最终返回一个单一值。 ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
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社区 版权所有