逻辑参考链接:移动端双指缩放图片JS事件的实践心得 « 张鑫旭-鑫空间-鑫生活
参考链接:双指缩放
<template>
<!-- 图片展示 -->
<el-image-viewer v-if="imgViewerVisible" @close="closePreview" :url-list="propsVal.imgList" />
<!-- 图片展示 -->
</template>
<script lang="ts" setup name="imageVIewer">
import { ref, nextTick } from '@vue/runtime-core';
import { IsMobileBrowser } from "../tools"
const propsVal = defineProps(
{
imgList: {
type: Array<String>,
}
}
)
// 是否显示
const imgViewerVisible = ref(true)
// 显示
function openImage() {
imgViewerVisible.value = true
imageVisibleHandle()
}
// 隐藏
function closeImage() {
imgViewerVisible.value = false
imageVisibleHandle()
}
function closePreview() {
closeImage()
return '关闭了'
}
// 容器变量
let container = document.querySelector('.el-image-viewer__img') as HTMLElement
let image_viewer__wrapper = document.querySelector('.el-image-viewer__wrapper') as HTMLElement
// 单指变量
let initialX = 0; // 初始点击X点位
let initialY = 0; // 初始点击Y点位
let offsetX = 0; // 盒子内距离点位的X轴
let offsetY = 0; // 盒子内距离点位的Y轴
let isSingle: boolean = true;//判断是否是单指操作
// 双指变量
const store = {
scale: 1
} as any;
// 双指触摸监听器功能实现
function wrapper_touchstartHandle(e: any) {
var touches = e.touches;
var events = touches[0];
var events2 = touches[1];
if (!e) {
return;
}
// 第一个触摸点的坐标
store.pageX = events.pageX;
store.pageY = events.pageY;
store.moveable = true;
if (events2) {
store.pageX2 = events2.pageX;
store.pageY2 = events2.pageY;
}
store.originScale = store.scale || 1;
}
// 双指拖拽监听器功能实现
function wrapper_touchmoveHandle(e: any) {
if (!store.moveable) {
return;
}
var touches = e.touches;
var events = touches[0];
var events2 = touches[1];
// 双指移动
if (events2) {
// 第2个指头坐标在touchmove时候获取
if (!store.pageX2) {
store.pageX2 = events2.pageX;
}
if (!store.pageY2) {
store.pageY2 = events2.pageY;
}
// 获取坐标之间的举例
var getDistance = function (start: any, stop: any) {
return Math.hypot(stop.x - start.x, stop.y - start.y);
};
// 双指缩放比例计算
var zoom = getDistance({
x: events.pageX,
y: events.pageY
}, {
x: events2.pageX,
y: events2.pageY
}) /
getDistance({
x: store.pageX,
y: store.pageY
}, {
x: store.pageX2,
y: store.pageY2
});
// 应用在元素上的缩放比例
var newScale = store.originScale * zoom;
// 最大缩放比例限制
if (newScale > 3) {
newScale = 3;
}
// 记住使用的缩放值
store.scale = newScale;
// 图像应用缩放效果
container.style.transform = 'scale(' + newScale + ')';
container.style.transition = "transform .3s";
}
}
// 双指离开听器功能实现
function touchendClear(e: any) {
isSingle = false
store.moveable = false;
delete store.pageX2;
delete store.pageY2;
}
// 单指触摸监听器功能实现
function container_touchstartHandle(e: any) {
// 当一只手指触摸时
isSingle = true
if (e.touches.length === 1 && isSingle) {
// 拿到当前的位置
initialX = e.touches[0].clientX;
initialY = e.touches[0].clientY;
// 拿到点位距离盒子的位置
offsetX = initialX - container.offsetLeft;
offsetY = initialY - container.offsetTop;
}
}
// 单指拖拽监听器功能实现
function container_touchmoveHandle(e: any) {
if (e.touches.length == 1 && isSingle) {
// 获取当前触摸点的位置
const currentX = e.touches[0].clientX;
const currentY = e.touches[0].clientY;
// 移动元素的位置
if (container.style.position != 'fixed') container.style.position = 'fixed'
container.style.left = (currentX - offsetX) + 'px';
container.style.top = (currentY - offsetY) + 'px';
}
}
// 图片显示隐藏处理
function imageVisibleHandle() {
// 监听图片打开关闭动作,进行双指缩放以及图片拖拽功能
nextTick(() => {
// 渲染完成后拿到盒子本体
container = document.querySelector('.el-image-viewer__img') as HTMLElement
image_viewer__wrapper = document.querySelector('.el-image-viewer__wrapper') as HTMLElement
if (imgViewerVisible.value) {
// 移动端隐藏按钮
if (IsMobileBrowser()) {
const button: HTMLElement = document.querySelector('.el-image-viewer__actions') as HTMLElement
button.style.display = 'none'
}
// 当 imgViewerVisible 变为 true 时,启用触摸屏幕缩放
// 双指触摸监听器
image_viewer__wrapper.addEventListener('touchstart', wrapper_touchstartHandle);
// 双指拖拽监听器
image_viewer__wrapper.addEventListener('touchmove', wrapper_touchmoveHandle);
// 双指离开监听器
image_viewer__wrapper.addEventListener('touchend', touchendClear);
// 停止触摸
image_viewer__wrapper.addEventListener('touchcancel', function () {
store.moveable = false;
delete store.pageX2;
delete store.pageY2;
});
// 单指触摸监听器
container.addEventListener('touchstart', container_touchstartHandle)
// 单指拖拽监听器
container.addEventListener('touchmove', container_touchmoveHandle)
} else {
// 如果是关闭就移除监听器并清除数据
if (!!image_viewer__wrapper) {
image_viewer__wrapper.removeEventListener('touchstart', wrapper_touchstartHandle)
image_viewer__wrapper.removeEventListener('touchmove', wrapper_touchmoveHandle)
image_viewer__wrapper.removeEventListener('touchend', touchendClear)
}
if (!!container) {
container.removeEventListener('touchstart', container_touchstartHandle)
container.removeEventListener('touchmove', container_touchmoveHandle)
}
}
})
}
defineExpose({
openImage,
closeImage
})
</script>
<style type="text/css"></style>
PS:IsMobileBrowser是一个判断是否为移动端设备的方法