首先讲一下所需工具:
如果你已经准备好了这些工具,接下来我们就可以开始制作基于touch.js和Zepto.js的图片查看器了。
首先我们需要先创建出HTML结构,这个结构比较简单,主要就是一个包含图片的div容器。
<div class="image-viewer">
<img src="example.jpg" alt="example image">
</div>
其中的class可以用于样式设置和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;
}
以上代码主要功能为设置图片容器为相对定位和隐藏溢出部分,同时设置图片为居中显示。
接下来我们就开始编写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、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开发中。
本文链接:http://task.lmcjl.com/news/8367.html