import { reactive } from "vue";
type StoreType = {
scale: number;
originScale: number;
pageX?: number;
pageY?: number;
pageX2?: number;
pageY2?: number;
moveable: boolean;
lastTranslateX: number;
lastTranslateY: number;
};
export default function (el: HTMLElement) {
const store = reactive<StoreType>({
scale: 1,
originScale: 1,
moveable: false,
lastTranslateX: 0,
lastTranslateY: 0
});
if (el) {
el.addEventListener("touchstart", function (event) {
const touches = event.touches;
const [events, events2] = touches;
event.preventDefault();
// 第一个触摸点的坐标
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;
});
}
el.addEventListener("touchmove", function (event) {
if (!store.moveable) {
return;
}
event.preventDefault();
const touches = event.touches;
const [events, events2] = touches;
if (events2) {
// 双指移动
// 第2个指头坐标在touchmove时候获取
if (!store.pageX2) {
store.pageX2 = events2.pageX;
}
if (!store.pageY2) {
store.pageY2 = events2.pageY;
}
// 获取坐标之间的举例
const getDistance = function (start, stop) {
return Math.hypot(stop.x - start.x, stop.y - start.y);
};
// 双指缩放比例计算
const 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 });
// 应用在元素上的缩放比例
let newScale = store.originScale * zoom;
// 最大缩放比例限制
if (newScale > 3) {
newScale = 3;
}
if (newScale < 1) {
newScale = 1;
store.lastTranslateX = 0;
store.lastTranslateY = 0;
}
// 记住使用的缩放值
store.scale = newScale;
// 图像应用缩放效果
el.style.transformOrigin = `${(events.pageX + events2.pageX) / 2 - store.lastTranslateX}px ${(events.pageY + events2.pageY) / 2 - store.lastTranslateY}px`;
el.style.transform = `scale(${store.scale}) `;
} else {
if (store.scale === 1) {
el.style.transform = "none";
} else {
// 单指移动
el.style.transform = `scale(${store.scale}) translate(${store.lastTranslateX + (events.pageX - (store.pageX || 0)) / store.scale}px,${store.lastTranslateY + (events.pageY - (store.pageY || 0)) / store.scale}px)`;
}
}
});
el.addEventListener("touchend", function () {
const styleStr = el.style.transform.split("translate(")?.[1]?.split(",");
store.lastTranslateX = parseFloat(styleStr?.[0]) || 0;
store.lastTranslateY = parseFloat(styleStr?.[1]) || 0;
store.moveable = false;
store.pageX2 = undefined;
store.pageY2 = undefined;
});
el.addEventListener("touchcancel", function () {
store.moveable = false;
store.pageX2 = undefined;
store.pageY2 = undefined;
});
}
以上代码单独一个文件useTouches.ts。
使用:import { useTouches } from "./useTouches";
const img = document.getElementById("day-img") as HTMLElement;
useTouches(img);