基于touch.js手势库+zepto.js插件开发图片查看器(滑动、缩放、双击缩放)

首先讲一下所需工具:

  • touch.js:一款轻量级的移动端手势库,用于实现图片的缩放、滑动等手势操作;
  • Zepto.js:一款轻量级的JavaScript库,可用于DOM操作、事件绑定等常见操作。

如果你已经准备好了这些工具,接下来我们就可以开始制作基于touch.js和Zepto.js的图片查看器了。

步骤一、创建HTML结构

首先我们需要先创建出HTML结构,这个结构比较简单,主要就是一个包含图片的div容器。

<div class="image-viewer">
  <img src="example.jpg" alt="example image">
</div>

其中的class可以用于样式设置和JS操作。

步骤二、调用touch.js和Zepto.js库

我们需要在HTML文件中引入touch.js和zepto.js库,代码如下:

<script src="./path/to/touch.js"></script>
<script src="./path/to/zepto.js"></script>

引入之后我们就可以使用库中的方法和函数了。

步骤三、添加基本样式

若要使图片查看器显示正常,我们需要为其添加一些基本样式,主要是设置图片容器的宽度、高度等。

.image-viewer {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

.image-viewer img {
  max-width: 100%;
  max-height: 100%;
  display: block;
  margin: auto;
}

以上代码主要功能为设置图片容器为相对定位和隐藏溢出部分,同时设置图片为居中显示。

步骤四、编写js代码实现手势操作

接下来我们就开始编写JavaScript代码来实现手势操作。

首先,我们需要给图片容器添加touchstart、touchmove、touchend事件,用于在触摸时实现滑动、缩放等操作。代码如下:

const imgViewer = document.querySelector('.image-viewer');

let initScale = 1; // 初始缩放比例
let curScale = 1; // 当前缩放比例
let prevDistance = 0; // 前一时刻的两个手指的距离
let startX, startY, moveX, moveY, lastMoveX = 0, lastMoveY = 0; // 手指的初始位置和移动距离
let isSingleTap = false; // 是否为单击事件
let isDoubleTap = false; // 是否为双击事件
let lastTapTime = null; // 上一次触摸结束的时间

let isTouchStart = false; // 是否触摸开始

imgViewer.addEventListener('touchstart', function(e) {
  e.preventDefault();
  isTouchStart = true;

  // 判断是否为双击事件
  let currentTapTime = Date.now();
  if (lastTapTime !== null && currentTapTime - lastTapTime < 300) {
    isDoubleTap = true;
  } else {
    isSingleTap = true;
    lastTapTime = currentTapTime;
  }

  // 获取初始位置
  startX = e.touches[0].pageX;
  startY = e.touches[0].pageY;

  // 重置相关值
  lastMoveX = moveX;
  lastMoveY = moveY;
  prevDistance = 0;
});

imgViewer.addEventListener('touchmove', function(e) {
  e.preventDefault();

  // 获取移动距离
  moveX = e.touches[0].pageX - startX + lastMoveX;
  moveY = e.touches[0].pageY - startY + lastMoveY;

  if (e.touches.length > 1) { // 处理双指操作
    isSingleTap = false;

    let distance = Math.sqrt(
      (e.touches[1].pageX - e.touches[0].pageX) ** 2 +
      (e.touches[1].pageY - e.touches[0].pageY) ** 2);

    if (prevDistance !== 0) {
      curScale = curScale * (distance / prevDistance);
      imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
    }
    prevDistance = distance;
  } else { // 处理单指操作
    isDoubleTap = false;
    curScale = initScale;
    imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
  }
});

imgViewer.addEventListener('touchend', function(e) {
  e.preventDefault();
  if (isSingleTap) {
    // 处理单击事件
  } else if (isDoubleTap) {
    // 处理双击事件
  }

  // 重置相关值
  prevDistance = 0;
  isSingleTap = false;
  isDoubleTap = false;

  // 是否触摸结束
  isTouchStart = false;
});

以上代码主要处理了以下事件:

  • touchstart:获取触摸开始的位置,并判断是否为单击或双击事件;
  • touchmove:获取触摸滑动的距离,并实现图片的移动和缩放操作;
  • touchend:处理单击和双击事件,同时重置相关变量。

步骤五、实现双击操作和缩放操作

实现双击操作主要需要在touchstart、touchend事件中对isDoubleTap进行判断,并在touchstart事件中记录下当前时间,用于判断两次触摸间隔是否小于300ms。若是,则视为双击。

imgViewer.addEventListener('touchstart', function(e) {
  // 判断是否为双击事件
  let currentTapTime = Date.now();
  if (lastTapTime !== null && currentTapTime - lastTapTime < 300) {
    isDoubleTap = true;
  } else {
    isSingleTap = true;
    lastTapTime = currentTapTime;
  }

  // ...
});

imgViewer.addEventListener('touchend', function(e) {
  // 处理双击事件
  if (isDoubleTap) {
    if (curScale === initScale) {
      // 如果当前缩放比例为1,则双击放大
      curScale = 2;
      imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
    } else {
      // 如果当前缩放比例大于1,则双击缩小至初始比例
      curScale = initScale;
      imgViewer.style.transform = `scale(${curScale}) translate(0, 0)`;
    }
  }

  // ...
});

实现缩放操作其实就是在touchmove事件中对curScale进行计算,并实时更新图片的缩放比例和位置。

imgViewer.addEventListener('touchmove', function(e) {
  // 获取移动距离
  moveX = e.touches[0].pageX - startX + lastMoveX;
  moveY = e.touches[0].pageY - startY + lastMoveY;

  if (e.touches.length > 1) { // 处理双指操作
    // ...

    if (prevDistance !== 0) {
      curScale = curScale * (distance / prevDistance);
      imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
    }

    // ...
  } else { // 处理单指操作
    // ...

    curScale = initScale;
    imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;

    // ...
  }
});

步骤六、完善单击事件和完整代码

最后,我们需要完善单击事件,通过判断触摸开始和触摸结束的时间间隔来区分单击和长按事件。代码如下:

imgViewer.addEventListener('touchstart', function(e) {
  // 记录触摸开始的时间
  touchStartTime = Date.now();
  // ...
});

imgViewer.addEventListener('touchend', function(e) {
  // 记录触摸结束的时间
  touchEndTime = Date.now();
  // 判断是否为单击事件或长按事件
  if (isTouchStart && touchEndTime - touchStartTime <= 350) {
    // 处理单击事件
  } else if (isTouchStart && touchEndTime - touchStartTime > 350) {
    // 处理长按事件
  }
  // ...
});

完整代码如下:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>图片查看器</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <style type="text/css">
    .image-viewer {
      width: 100%;
      height: 100%;
      overflow: hidden;
      position: relative;
    }

    .image-viewer img {
      max-width: 100%;
      max-height: 100%;
      display: block;
      margin: auto;
    }
  </style>
</head>

<body>
  <div class="image-viewer">
    <img src="example.jpg" alt="example image">
  </div>
  <script src="./path/to/touch.js"></script>
  <script src="./path/to/zepto.js"></script>
  <script type="text/javascript">
    const imgViewer = document.querySelector('.image-viewer');

    let initScale = 1; // 初始缩放比例
    let curScale = 1; // 当前缩放比例
    let prevDistance = 0; // 前一时刻的两个手指的距离
    let startX, startY, moveX, moveY, lastMoveX = 0, lastMoveY = 0; // 手指的初始位置和移动距离
    let isSingleTap = false; // 是否为单击事件
    let isDoubleTap = false; // 是否为双击事件
    let lastTapTime = null; // 上一次触摸结束的时间

    let isTouchStart = false; // 是否触摸开始
    let touchStartTime, touchEndTime; // 触摸开始和结束的时间

    imgViewer.addEventListener('touchstart', function(e) {
      e.preventDefault();

      // 判断是否为双击事件
      let currentTapTime = Date.now();
      if (lastTapTime !== null && currentTapTime - lastTapTime < 300) {
        isDoubleTap = true;
      } else {
        isSingleTap = true;
        lastTapTime = currentTapTime;
      }

      // 记录触摸开始的位置
      startX = e.touches[0].pageX;
      startY = e.touches[0].pageY;

      // 重置相关值
      lastMoveX = moveX;
      lastMoveY = moveY;
      prevDistance = 0;

      // 记录触摸开始的事件
      touchStartTime = Date.now();

      isTouchStart = true;
    });

    imgViewer.addEventListener('touchmove', function(e) {
      e.preventDefault();

      // 获取移动距离
      moveX = e.touches[0].pageX - startX + lastMoveX;
      moveY = e.touches[0].pageY - startY + lastMoveY;

      if (e.touches.length > 1) { // 处理双指操作
        isSingleTap = false;

        let distance = Math.sqrt(
          (e.touches[1].pageX - e.touches[0].pageX) ** 2 +
          (e.touches[1].pageY - e.touches[0].pageY) ** 2);

        if (prevDistance !== 0) {
          curScale = curScale * (distance / prevDistance);
          imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
        }
        prevDistance = distance;
      } else { // 处理单指操作
        isDoubleTap = false;
        curScale = initScale;
        imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
      }
    });

    imgViewer.addEventListener('touchend', function(e) {
      e.preventDefault();

      // 记录触摸结束的时间
      touchEndTime = Date.now();

      if (isSingleTap) {
        // 处理单击事件
        if (isTouchStart && touchEndTime - touchStartTime <= 350) {
          // 处理单击事件
        }
      } else if (isDoubleTap) {
        // 处理双击事件
        if (curScale === initScale) {
          // 如果当前缩放比例为1,则双击放大
          curScale = 2;
          imgViewer.style.transform = `scale(${curScale}) translate(${moveX}px, ${moveY}px)`;
        } else {
          // 如果当前缩放比例大于1,则双击缩小至初始比例
          curScale = initScale;
          imgViewer.style.transform = `scale(${curScale}) translate(0, 0)`;
        }
      }

      // 重置相关值
      prevDistance = 0;
      isSingleTap = false;
      isDoubleTap = false;

      // 是否触摸结束
      isTouchStart = false;
    });
  </script>
</body>

</html>

以上就是基于touch.js和zepto.js的图片查看器的完整攻略,其中包含了双击、滑动、缩放等多个手势操作,可以应用于各类移动端H5网站和APP开发中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于touch.js手势库+zepto.js插件开发图片查看器(滑动、缩放、双击缩放) - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JavaScript的查询机制LHS和RHS解析

    JavaScript中存在两种类型的查询机制,即左查询(LHS)和右查询(RHS)。这两种查询机制可以帮助我们理解JavaScript变量的赋值过程。下面详细讲解一下这两种查询机制。 LHS查询 LHS查询通常发生在变量被赋值的时候,这种查询的目的是为了找到变量所在的内存地址,当变量所在的内存地址存在时,就可以把该值赋给变量。如果变量所在内存地址在运行时不存…

    JavaScript 2023年5月28日
    00
  • javascript的函数第2/3页

    让我们来详细讲解“JavaScript的函数第2/3页”的完整攻略。 函数的声明 函数是 JavaScript 中的重要组成部分,它可以使我们编写可重用的代码。在 JavaScript 中,函数有两种声明方式:函数声明和函数表达式。 函数声明 函数声明是最常用和最熟悉的方式。它使用 function 关键字来定义一个函数,并给它取一个名称。语法如下: fun…

    JavaScript 2023年5月18日
    00
  • JavaScript 学习点滴记录

    JavaScript 学习指南 前言 JavaScript 是一种脚本语言,普遍应用于 Web 开发中。JavaScript 是一种动态的、弱类型解释性语言,并且具有多范式的特性,如面向对象、命令式、声明式等。 在学习 JavaScript 的过程中,我们需要学习它的基本语法和常见的应用。随着学习的深入,我们可以从以下几个方面来拓展自己的知识面: 前端框架和…

    JavaScript 2023年5月27日
    00
  • HTML中不支持静态Expando的元素的问题

    “HTML中不支持静态Expando的元素的问题”指的是在某些HTML元素上添加特定属性或JS对象时,如果该元素不支持静态Expando,则可能会导致问题。通常,此类问题表现为少量JS工作正常,大量JS工作不正常。 以下是解决“HTML中不支持静态Expando的元素的问题”的攻略: 1.了解什么是静态Expando Expando是为DOM元素添加的自定义…

    JavaScript 2023年6月10日
    00
  • blob转换成string格式同步调用问题解决分析

    问题描述: 在开发过程中,我们有时会需要将Blob数据类型转换为String类型。Blob对象表示不可变、原始数据的类文件对象。但是,Blob类型的数据转换为String类型时,会涉及到异步回调的执行问题,常常导致数据无法按预期输出或报错。所以,本文将会讲解 Blob转换为String格式的同步调用问题,并提供解决方案。 解决方案: 使用FileReader…

    JavaScript 2023年6月11日
    00
  • Javascript删除指定元素节点的方法

    删除指定元素节点的方法在Javascript中有多种实现方式,下面给出其中两种示例说明。 方法一:使用removeChild()方法删除节点 通过使用removeChild()方法可以删除指定的元素节点。具体实现步骤如下: 获取要删除的节点; 获取要删除节点的父节点; 调用父节点的removeChild()方法,删除指定的子节点。 示例代码如下: // 获取…

    JavaScript 2023年6月10日
    00
  • Js利用console计算代码运行时间的方法示例

    当我们需要测试我们写的代码的运行时间以找到性能瓶颈时,可以使用JavaScript中的console对象来帮助我们计算代码运行的时间。下面是使用console计算代码运行时间的方法示例及其详细攻略: 显式地调用console.time()方法和console.timeEnd()方法 console.time()方法可以起到计时的作用,它需要传入一个唯一的标识…

    JavaScript 2023年5月27日
    00
  • 利用location.hash实现跨域iframe自适应

    实现跨域iframe自适应的首要问题是通过JavaScript获取iframe的高度。然而,由于同源策略的限制,无法直接获取跨域iframe的高度。为了解决这个问题,我们可以利用iframe的hash值和window.location.hash属性。 具体实现步骤如下: 1.在iframe页面中设置hash值 在iframe页面中添加以下代码: // 获取i…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部