touch手势事件及功能封装

在现代Web开发中,移动设备的普及使得触摸屏交互成为了一个重要的方面。

JavaScript中的Touch事件为开发者提供了处理触摸屏输入的能力,从而实现更丰富的用户体验。

本文将深入探讨JavaScript中的Touch事件,涵盖基本概念、事件类型、事件属性以及实际应用。

基本概念

首先,要注意touch事件是在移动设备上使用的,如智能手机和平板电脑,以及支持触摸的笔记本电脑。

Touch事件是指移动设备上用户通过触摸屏幕进行交互所触发的事件。这些事件包括触摸开始、移动、结束以及取消等。

通过监听这些事件,开发者可以捕捉并处理触摸交互的细节。它允许捕捉用户在触摸设备上的操作,例如点击、滑动、缩放等。

事件类型

  • touchstart:当用户开始触摸屏幕时触发,标识触摸操作的开始。

  • touchmove:在用户触摸屏幕后,随着手指的移动持续触发,表示手指在屏幕上的滑动操作。

  • touchend:当用户从屏幕上移开手指时触发,表示触摸操作的结束。

  • touchcancel:在某些情况下(如系统级的中断),触摸操作可能被取消,此时会触发这个事件。

事件对象的属性

每个touch事件都有一个事件对象,其中包含关于触摸的各种信息。以下是一些常见的事件对象属性:

  • touches:一个包含所有当前处于活动状态的触摸点的列表,是一个Touch对象数组。

  • targetTouches:一个包含当前事件目标上的所有触摸点的列表,是一个Touch对象数组。

  • changedTouches:一个包含最近发生变化的触摸的列表(比如在touchstart中,它只会包含一个新的触摸,而在touchmove和touchend中,它会包含有变化的触摸),无论它们是否位于当前事件目标元素上。也是一个Touch对象数组。

每个Touch对象都有一些属性,如:

  • identifier:触摸点的唯一标识符。一次触摸动作(我们指的是手指的触摸)在平 面上移动的整个过程中,该标识符不变。
  • target:与触摸点关联的DOM元素。
  • clientXclientY:触摸点相对于浏览器窗口的坐标。
  • pageXpageY:触摸点相对于整个页面的坐标。
  • screenXscreenY:触摸点相对于屏幕的坐标。

下面是一个简单的代码示例,演示如何使用touch事件来处理触摸操作

// 获取元素
const touchElement = document.getElementById('touch-element');

// 添加事件监听器
touchElement.addEventListener('touchstart', handleTouchStart);
touchElement.addEventListener('touchmove', handleTouchMove);
touchElement.addEventListener('touchend', handleTouchEnd);

// 处理touchstart事件
function handleTouchStart(event) {
  event.preventDefault(); // 阻止默认的触摸行为
  const touch = event.touches[0]; // 获取第一个触摸点
  console.log('Touch started at:', touch.clientX, touch.clientY);
}

// 处理touchmove事件
function handleTouchMove(event) {
  const touch = event.touches[0];
  console.log('Touch moved to:', touch.clientX, touch.clientY);
}

// 处理touchend事件
function handleTouchEnd(event) {
  console.log('Touch ended');
}

在这个示例中,我们首先获取一个DOM元素(在这里假设有一个id为touch-element的元素),然后为touchstart、touchmove和touchend事件添加了相应的事件监听器。每个事件处理函数都会提取事件对象中的触摸信息,并进行适当的操作。

请注意,实际应用中可能需要更复杂的逻辑来处理触摸操作,例如跟踪多个触摸点、处理滑动手势等。

总之,使用JavaScript中的touch事件,可以轻松地在移动设备上实现各种触摸操作的响应和处理。

touch事件封装

单击,双击

click事件在移动端300ms延迟问题:当你click一次之后,会经过300ms之后检测是否再有一次click,如果有的话,就会缩放页面,否则的话就是一个click事件。由此我们可以封装h5端的单击,双击事件。

// 获取触摸目标元素
const touchElement = document.getElementById('your-element-id');

let lastClickTime = 0;
let touchTimeout;

// 触摸事件处理函数
function handleTouch(event) {
  const currentTime = new Date().getTime();
  
  if (currentTime - lastClickTime < 300) { // 判断两次点击的时间间隔
    clearTimeout(touchTimeout);
    // 处理双击事件
    console.log('Double click');
  } else {
    // 处理单击事件
    touchTimeout = setTimeout(() => {
      console.log('Single click');
    }, 300);
  }
  
  lastClickTime = currentTime;
}

// 为目标元素绑定触摸事件处理函数
touchElement.addEventListener('touchend', handleTouch);

在这个例子中,我们创建了一个handleTouch函数来处理触摸事件。通过记录上一次点击的时间戳,我们可以计算两次点击之间的时间间隔,从而判断是单击还是双击事件。如果两次点击的时间间隔小于300毫秒,则认为是双击,否则认为是单击。

滑动方向(上下左右)

距离

可以根据触摸点的坐标变化来判断滑动的方向。

// 获取触摸目标元素
const touchElement = document.getElementById('your-element-id');

let startX = 0;
let startY = 0;

// 触摸事件处理函数
function handleTouchStart(event) {
  const touch = event.touches[0];
  startX = touch.clientX;
  startY = touch.clientY;
}

function handleTouchEnd(event) {
  const touch = event.changedTouches[0];
  const deltaX = touch.clientX - startX;
  const deltaY = touch.clientY - startY;

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    if (deltaX > 0) {
      console.log('向右滑动');
    } else {
      console.log('向左滑动');
    }
  } else {
    if (deltaY > 0) {
      console.log('向下滑动');
    } else {
      console.log('向上滑动');
    }
  }
}

// 为目标元素绑定触摸事件处理函数
touchElement.addEventListener('touchstart', handleTouchStart);
touchElement.addEventListener('touchend', handleTouchEnd);

在这个例子中,我们使用了touchstart事件来记录滑动开始时的触摸点坐标,然后在touchend事件中计算触摸点的坐标变化(即滑动的距离),并根据坐标变化的方向来判断滑动的方向(左右或上下)。

角度

  • 坐标系:

    原点通常位于屏幕左上角(0, 0)。水平方向向右增加,垂直方向向下增加。与常规的数学坐标系的垂直方向有差异。

  • Math.atan2(y,x) 函数,计算角度的弧度值

    • angel=Math.atan2(y,x)

    • x 指定点的 x 坐标,y 指定点的 y 坐标

    • angel是一个弧度值(可以比喻为直角三角形对角的角,其中 x 是邻边边长,而 y 是对边边长)

  • Math.atan2(y,x)*180/Math.PI 转换为角度

// 获取触摸目标元素
const touchElement = document.getElementById('your-element-id');

let startX = 0;
let startY = 0;

// 触摸事件处理函数
function handleTouchStart(event) {
  const touch = event.touches[0];
  startX = touch.clientX;
  startY = touch.clientY;
}

function handleTouchEnd(event) {
  const touch = event.changedTouches[0];
  const endX = touch.clientX;
  const endY = touch.clientY;

  const deltaX = endX - startX;
  const deltaY = endY - startY;

  // 计算滑动角度
  const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);

  // 判断滑动方向
  if (angle >= -45 && angle < 45) {
    console.log('向右滑动');
  } else if (angle >= 45 && angle < 135) {
    console.log('向下滑动');
  } else if (angle >= -135 && angle < -45) {
    console.log('向上滑动');
  } else {
    console.log('向左滑动');
  }
}

// 为目标元素绑定触摸事件处理函数
touchElement.addEventListener('touchstart', handleTouchStart);
touchElement.addEventListener('touchend', handleTouchEnd);

使用Math.atan2函数来计算滑动的角度,然后根据角度范围来判断滑动的方向。具体来说:

  • 角度在 -45 到 45 度之间,判断为向右滑动。
  • 角度在 45 到 135 度之间,判断为向下滑动。
  • 角度在 -135 到 -45 度之间,判断为向上滑动。
  • 其他情况判断为向左滑动。

缩放

// 获取需要缩放的元素
const targetElement = document.getElementById('yourElementId');

// 初始触摸点间的距离和初始缩放比例
let initialDistance = 0;
let initialScale = 1;

// 开始触摸时的处理函数
function handleTouchStart(event) {
  const touches = event.touches;
  if (touches.length >= 2) {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    initialDistance = Math.sqrt(dx * dx + dy * dy);
  }
}

// 触摸移动时的处理函数
function handleTouchMove(event) {
  const touches = event.touches;
  if (touches.length >= 2) {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    const currentDistance = Math.sqrt(dx * dx + dy * dy);

    // 计算缩放比例
    const scale = currentDistance / initialDistance;

    // 应用缩放
    targetElement.style.transform = `scale(${scale})`;
  }
}

// 触摸结束时的处理函数
function handleTouchEnd() {
  // 重置缩放
  targetElement.style.transform = 'scale(1)';
}

// 添加触摸事件监听器
targetElement.addEventListener('touchstart', handleTouchStart);
targetElement.addEventListener('touchmove', handleTouchMove);
targetElement.addEventListener('touchend', handleTouchEnd);

在这个示例中,我们定义了三个处理函数来处理不同的触摸事件。

  • handleTouchStart 函数在触摸开始时获取初始触摸点间的距离和初始缩放比例。
  • handleTouchMove 函数在触摸移动时计算当前触摸点间的距离并应用缩放。
  • handleTouchEnd 函数在触摸结束时重置缩放。然后,我们通过添加监听器将这些处理函数绑定到相应的触摸事件上。

旋转

旋转手势通常涉及到两个触摸点的移动变化,类似于之前提到的缩放功能。

// 获取需要旋转的元素
const targetElement = document.getElementById('yourElementId');

// 初始触摸点的角度
let initialAngle = 0;

// 开始触摸时的处理函数
function handleTouchStart(event) {
  const touches = event.touches;
  if (touches.length >= 2) {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    initialAngle = Math.atan2(dy, dx);
  }
}

// 触摸移动时的处理函数
function handleTouchMove(event) {
  const touches = event.touches;
  if (touches.length >= 2) {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    const currentAngle = Math.atan2(dy, dx);

    // 计算旋转角度
    const angleDelta = currentAngle - initialAngle;

    // 应用旋转
    targetElement.style.transform = `rotate(${angleDelta}rad)`;
  }
}

// 触摸结束时的处理函数
function handleTouchEnd() {
  // 重置旋转
  targetElement.style.transform = 'rotate(0)';
}

// 添加触摸事件监听器
targetElement.addEventListener('touchstart', handleTouchStart);
targetElement.addEventListener('touchmove', handleTouchMove);
targetElement.addEventListener('touchend', handleTouchEnd);

在这个示例中,我们使用 Math.atan2 函数来计算触摸点与 x 轴的夹角,从而得到旋转角度。

  • handleTouchStart 函数获取初始触摸点的角度,
  • 而 handleTouchMove 函数计算当前触摸点的角度变化,并将其应用于元素的旋转变换。
  • 最后,handleTouchEnd 函数用于重置旋转效果。

常用功能封装

滑动图片浏览

假设有一个包含多张图片的画廊,希望用户可以在移动设备上滑动浏览这些图片。

HTML 结构:

<div id="gallery">
  <img src="image1.jpg" alt="Image 1">
  <img src="image2.jpg" alt="Image 2">
  <img src="image3.jpg" alt="Image 3">
</div>

CSS 样式(简化):

#gallery {
  display: flex;
  overflow: hidden;
  white-space: nowrap;
}

#gallery img {
  width: 100%;
  height: auto;
  display: inline-block;
}

JavaScript 代码:

const gallery = document.getElementById('gallery');
let startX = 0;
let scrolling = false;

gallery.addEventListener('touchstart', handleTouchStart);
gallery.addEventListener('touchmove', handleTouchMove);
gallery.addEventListener('touchend', handleTouchEnd);

function handleTouchStart(event) {
  if (event.touches.length === 1) {
    startX = event.touches[0].pageX;
    scrolling = true;
  }
}

function handleTouchMove(event) {
  if (!scrolling) return;

  const touch = event.touches[0];
  const distanceX = touch.pageX - startX;
  gallery.scrollLeft -= distanceX;
  startX = touch.pageX;
}

function handleTouchEnd() {
  scrolling = false;
}

在这个案例中,我们使用touch事件来实现了一个简单的图片浏览器。用户可以在画廊中水平滑动以浏览不同的图片。

  • touchstart事件中,我们记录了触摸开始时的横坐标,并设置了一个标志来表示正在滑动。
  • touchmove事件中,我们计算当前触摸点与上一个触摸点之间的距离,并根据这个距离来调整画廊的滚动位置,实现图片的平滑滑动。
  • touchend事件中,我们将滑动标志设置为false,表示滑动已经结束。

请注意,这只是一个简化的案例,实际中可能需要处理更多的细节,例如边界检查、惯性滚动等。

实现拖拽操作

实现拖拽操作是touch事件中的一个常见应用。下面是一个简单的示例,演示如何使用touch事件来实现基本的拖拽操作。

const draggableElement = document.getElementById('draggable-element');
let initialX = 0;
let initialY = 0;
let distanceX = 0;
let distanceY = 0;
let isDragging = false;

draggableElement.addEventListener('touchstart', handleTouchStart);
draggableElement.addEventListener('touchmove', handleTouchMove);
draggableElement.addEventListener('touchend', handleTouchEnd);

function handleTouchStart(event) {
  isDragging = true;
  const touch = event.touches[0];
  initialX = touch.clientX - distanceX;
  initialY = touch.clientY - distanceY;
}

function handleTouchMove(event) {
  if (!isDragging) return;
  const touch = event.touches[0];
  distanceX = touch.clientX - initialX;
  distanceY = touch.clientY - initialY;
  updateElementPosition();
}

function handleTouchEnd() {
  isDragging = false;
}

function updateElementPosition() {
  draggableElement.style.transform = `translate(${distanceX}px, ${distanceY}px)`;
}

在这个示例中,我们使用

  • touchstart事件来记录初始触摸点的位置,
  • touchmove事件来更新元素的位置,
  • touchend事件来标记拖拽结束。

当用户触摸元素并滑动手指时,元素将会跟随手指的移动而移动。注意,这只是一个简单的示例,实际中可能需要更多的功能,如边界限制、惯性效果等。

在这个基础上,可以根据需要添加更多的交互特性,例如限制拖拽范围、添加释放动画等,以实现更好的用户体验。

游戏角色移动、跳跃

使用touch事件来实现角色的移动、跳跃等动作可以为移动端游戏提供交互性。以下是一个示例,展示如何使用touch事件来控制角色的移动和跳跃动作。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Touch Control Example</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    #character {
      width: 50px;
      height: 50px;
      background-color: blue;
      position: absolute;
    }
  </style>
</head>
<body>
  <div id="character"></div>

  <script>
    const character = document.getElementById('character');
    let characterX = 0;
    let characterY = 0;
    let isJumping = false;

    document.addEventListener('touchstart', handleTouchStart);
    document.addEventListener('touchend', handleTouchEnd);

    function handleTouchStart(event) {
      const touchX = event.touches[0].clientX;
      const touchY = event.touches[0].clientY;

      if (touchX < window.innerWidth / 2) {
        moveLeft();
      } else {
        moveRight();
      }
    }

    function handleTouchEnd() {
      if (!isJumping) {
        jump();
      }
    }

    function moveLeft() {
      characterX -= 10;
      updateCharacterPosition();
    }

    function moveRight() {
      characterX += 10;
      updateCharacterPosition();
    }

    function jump() {
      isJumping = true;
      characterY -= 100;
      updateCharacterPosition();

      setTimeout(() => {
        characterY += 100;
        updateCharacterPosition();
        isJumping = false;
      }, 1000);
    }

    function updateCharacterPosition() {
      character.style.left = characterX + 'px';
      character.style.top = characterY + 'px';
    }
  </script>
</body>
</html>

在这个示例中,我们创建了一个简单的角色元素,当触摸屏幕左半部分时,角色向左移动;触摸屏幕右半部分时,角色向右移动;触摸屏幕时角色跳跃。请注意,这只是一个基础示例,实际中可能需要更多的逻辑和交互细节。

可以根据的需求扩展此示例,例如添加更多的控制选项、调整角色移动速度、添加背景、碰撞检测等。这个示例提供了一个基本的框架,可以根据游戏的需求进行定制和扩展。

封装手写板功能

当希望实现一个能够应对复杂情况的手写板时,可能需要添加更多的功能和交互细节。以下是一个更完整的手写板案例,其中包括不同画笔样式、颜色选择、清除画布、保存图像等功能。

HTML 结构:

<canvas id="canvas" width="600" height="400"></canvas>
<div id="controls">
  <button id="clear-button">Clear</button>
  <input type="color" id="color-picker" value="#000000">
  <select id="brush-size">
    <option value="2">Thin</option>
    <option value="5" selected>Medium</option>
    <option value="10">Thick</option>
  </select>
</div>

CSS 样式(可选):

#canvas {
  border: 1px solid black;
}

#controls {
  margin-top: 10px;
}

JavaScript 代码:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;

function updateCanvasSize() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}

window.addEventListener('resize', updateCanvasSize);
updateCanvasSize();

canvas.addEventListener('touchstart', startDrawing);
canvas.addEventListener('touchmove', draw);
canvas.addEventListener('touchend', stopDrawing);

function startDrawing(event) {
  isDrawing = true;
  const touch = event.touches[0];
  const x = touch.pageX - canvas.offsetLeft;
  const y = touch.pageY - canvas.offsetTop;
  ctx.beginPath();
  ctx.moveTo(x, y);
}

function draw(event) {
  if (!isDrawing) return;

  const touch = event.touches[0];
  const x = touch.pageX - canvas.offsetLeft;
  const y = touch.pageY - canvas.offsetTop;
  const brushSize = parseInt(document.getElementById('brush-size').value);
  const color = document.getElementById('color-picker').value;

  ctx.lineWidth = brushSize;
  ctx.strokeStyle = color;
  ctx.lineTo(x, y);
  ctx.stroke();
}

function stopDrawing() {
  isDrawing = false;
  ctx.closePath();
}

// 清除画布按钮
const clearButton = document.getElementById('clear-button');
clearButton.addEventListener('click', clearCanvas);

function clearCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

// 保存图像按钮
const saveButton = document.getElementById('save-button');
saveButton.addEventListener('click', saveCanvas);

function saveCanvas() {
  const image = canvas.toDataURL('image/png');
  const link = document.createElement('a');
  link.href = image;
  link.download = 'drawing.png';
  link.click();
}

在这个手写板案例中,我们添加了如下:

  • 画笔颜色和粗细的选择
  • 清除画布功能
  • 保存绘制图像功能
  • 窗口大小调整的事件监听器

通过在颜色选择器、画笔粗细选择器和按钮上添加事件监听器,我们可以实现更灵活的绘图操作。用户可以根据需求选择画笔颜色、粗细,清除画布,以及将绘制结果保存为图像文件。通过在窗口大小发生变化时重新设置画布的宽度和高度,我们可以避免屏幕旋转带来的绘制问题。

全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务