记录下以前实现的双指滑动操控图片大小的功能。
ps:图片缩放时有点抖动,感觉要再调调参数。有什么建议欢迎留言~
【效果图】
组件-HTML部分代码
<template>
<div>
<scroll-view
scroll-x="true"
scroll-y="true"
style="max-width: 350px; max-height: 700px; white-space: nowrap"
>
<image
:src="props.imageUrl"
mode="widthFix"
@load="imageLoad"
:style="{
width: imageWidth,
height: imageHeight,
display: 'inline-block',
}"
@touchmove="TouchMove"
@touchstart="TouchStart"
@touchend="TouchEnd"
></image>
</scroll-view>
</div>
</template>
组件-ts部分代码
<script lang="ts" setup>
import { ref } from "vue";
const props = defineProps({
imageUrl: {
type: String,
default: "",
},
});
// 1. 定义两个变量计算双指的两个点X、Y坐标之间的距离
const moveX = ref<number>(0);
const moveY = ref<number>(0);
// 2. 定义变量表示两个点之间的距离,用勾股定理计算
// 3. 老距离:手指刚放在屏幕上的距离;
const oldDistance = ref<number>(0);
// 4. 新距离:移动后的距离。
const newDistance = ref<number>(0);
// 5. 距离:新距离-老距离。是正数,说明图片要放大,是负数,说明图片要缩小
const distanceDiff = ref<number>(0);
const imageBaseHeight = ref<number>(0);
const imageBaseWidth = ref<number>(0);
const imageHeight = ref<string>("");
const imageWidth = ref<string>("");
const imageScale = ref<number>(1);
const imageNewScale = ref<number>(1);
const canMove = ref<boolean>(false);
const imageLoad = (imageInfo) => {
// 在图片加载完成时获取图片的宽度和高度
imageBaseHeight.value = imageInfo.detail.height;
imageBaseWidth.value = imageInfo.detail.width;
};
const TouchStart = (touchInfo) => {
// 触摸事件的对象中属性touches可以获取屏幕中触摸点的信息。是一个数组,双指触摸就是有两个值
// clientX 和 clientY:距离屏幕可显示区域左上角距离
if (touchInfo.touches.length === 2) {
canMove.value = true;
moveX.value = touchInfo.touches[1].clientX - touchInfo.touches[0].clientX;
moveY.value = touchInfo.touches[1].clientY - touchInfo.touches[0].clientY;
// 刚触摸时赋值老距离
oldDistance.value = Math.sqrt(
moveX.value * moveX.value + moveY.value * moveY.value
);
} else {
// 单指触摸或双指以上不做处理
return ;
}
};
const TouchMove = (touchInfo) => {
// 双指触摸,且没有结束触摸时执行下面的计算
if (touchInfo.touches.length === 2 && canMove.value) {
moveX.value = touchInfo.touches[1].clientX - touchInfo.touches[0].clientX;
moveY.value = touchInfo.touches[1].clientY - touchInfo.touches[0].clientY;
// 开始移动时赋值新的距离
newDistance.value = Math.sqrt(
moveX.value * moveX.value + moveY.value * moveY.value
);
distanceDiff.value = newDistance.value - oldDistance.value;
imageNewScale.value = imageScale.value + 0.002 * distanceDiff.value;
// 最大缩放倍数为2.5倍
// if (imageNewScale.value >= 2.5) {
// imageNewScale.value = 2.5;
// }
// 不加最小缩放,因为获取到的图片基础宽高的单位(不知道是啥单位,试不出来)和计算用的单位(用的rpx)不统一,加上最小缩放会导致图片显示不全
// if (imageNewScale.value <= 1) {
// imageNewScale.value = 1;
// }
imageHeight.value =
String(imageBaseHeight.value * imageNewScale.value) + "rpx";
imageWidth.value =
String(imageBaseWidth.value * imageNewScale.value) + "rpx";
// 每次基于上次的缩放比例进行缩放
imageScale.value = imageNewScale.value;
oldDistance.value = Math.sqrt(
moveX.value * moveX.value + moveY.value * moveY.value
);
} else {
// 单指触摸或双指以上或结束触摸则不做处理
return ;
}
};
const TouchEnd = () => {
canMove.value = false;
};
</script>