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

yizhihongxing

首先讲一下所需工具:

  • 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日

相关文章

  • JS中的THIS和WINDOW.EVENT.SRCELEMENT详解

    JS中的this关键字 什么是this? 在JavaScript中,this是一个特殊的关键字,它在函数内部起着重要的作用,表明当前代码执行的上下文。当代码执行时,this的值会根据代码的上下文而动态的改变。 this指向的值 this关键字指向的是当前代码的“拥有者”或“执行者”,它的值会因为当前代码所在的位置而变化。下面是几个示例: this指向wind…

    JavaScript 2023年6月10日
    00
  • js流动式效果显示当前系统时间

    实现JS流动式效果显示当前系统时间,可以通过以下步骤实现: 第一步:获取当前时间 JavaScript中可以通过Date()对象获取当前的系统时间。 var now = new Date(); var hour = now.getHours(); //小时 var minute = now.getMinutes(); //分钟 var second = no…

    JavaScript 2023年5月27日
    00
  • JavaScript初学者应注意的七个细节小结

    JavaScript初学者应注意的七个细节小结 1. 关于变量 使用关键字var声明变量。没有使用var关键字声明的变量将会自动声明为全局变量,可能会影响其他页面的JavaScript代码。 声明变量时要加上适当的注释,方便自己和其他人阅读代码。 变量名应该简洁明了,便于理解,不要使用拼音或者将多个单词缩写在一起的方式命名变量。 示例: // 不好的示例 v…

    JavaScript 2023年6月10日
    00
  • JS 中Json字符串+Cookie+localstorage

    以下是对于“JS中JSON字符串+Cookie+localStorage”的完整攻略: 1. 什么是JSON字符串? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于JavaScript语言的子集,由Douglas Crockford在2001年首次提出。JSON字符串是指符合JSON格式规范的字符串。 JS…

    JavaScript 2023年5月27日
    00
  • 前端中的JS使用调试技巧

    下面介绍一下“前端中的JS使用调试技巧”的完整攻略: 检查代码 在JS开发过程中,一些普遍的错误是输错单词,缺少/多写了一个符号,语法错误等。这些问题都可以通过检查代码来解决。下面是一些检查代码的技巧: 1. 使用Console 使用Console进行 debug 是最基本的调试方法之一。Console 是一个在浏览器中开发人员工具里的选项卡,它允许开发人员…

    JavaScript 2023年5月18日
    00
  • webpack实现热更新(实施同步刷新)

    webpack实现热更新是在开发过程中非常常见的需求,它可以在代码修改后自动刷新页面,使开发人员能够更方便地查看效果。下面是实现webpack热更新的完整攻略: 1. 配置webpack-dev-server webpack-dev-server是webpack中的一个开发服务器,它可以实现热更新,而我们只需要在启动webpack-dev-server时添加…

    JavaScript 2023年6月1日
    00
  • 跟我学习javascript的异步脚本加载

    下面我就为您详细讲解“跟我学习javascript的异步脚本加载”的完整攻略。 前言 网页应用程序通常需要使用JavaScript来实现复杂的交互逻辑。JavaScript是一种单线程语言,当代码需要联网或执行耗时操作时,会出现页面阻塞的现象,这就导致了JavaScript执行速度直接影响到用户的交互体验。因此,为了解决这个问题,JavaScript提供了一…

    JavaScript 2023年5月27日
    00
  • js获取字符串最后一位方法汇总

    JS获取字符串最后一位方法汇总 在JS开发过程中,获取字符串最后一位是一个很常见的需求。下面将对常见的获取字符串最后一位的方法进行汇总并做详细讲解。 方法一:使用字符串的slice方法 使用字符串的slice方法可以获取字符串从指定位置开始到指定位置结束的子串,当指定结束位置为-1时,即可得到字符串的最后一个字符。 var str = ‘hello’; va…

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