class Gesture {
private element: HTMLElement
private istouch: boolean = false
private initX: number = 0
private initY: number = 0
private lastDistance: number = 0
private scale: number = 1
private minScale: number = 0.5 // 最小缩放比例
private maxScale: number = 2 // 最大缩放比例
private elementW: number = 375 // 容器宽高
private elementH: number = 500
constructor(element: HTMLElement) {
this.element = element
this.elementW = element.offsetWidth
this.elementH = element.offsetHeight
this.attachEventListeners()
}
// 监听触摸事件
private attachEventListeners() {
this.element.addEventListener('touchstart', this.handleTouchStart.bind(this), false)
this.element.addEventListener('touchmove', this.handleTouchMove.bind(this), false)
this.element.addEventListener('touchend', this.handleTouchEnd.bind(this), false)
}
private handleTouchStart(event: TouchEvent) {
// 可以根据需要初始化平移或缩放所需的数据
this.istouch = true
if (event.touches.length === 1) {
// 记录初始触摸点
const touch = event.touches[0]
this.initX = touch.clientX
this.initY = touch.clientY
} else if (event.touches.length === 2) {
// 记录当前缩放比例
this.lastDistance = this.getDistance(event)
}
}
private handleTouchMove(event: TouchEvent) {
if (event.touches.length === 1 && this.istouch) {
// 处理平移
this.pan(event)
} else if (event.touches.length === 2 && this.istouch) {
// 处理缩放
this.zoom(event)
}
}
private handleTouchEnd() {
// 处理触摸结束后的逻辑
this.istouch = false
}
// 平移
private pan(event: TouchEvent) {
const touch = event.touches[0]
const deltaX = touch.clientX - this.initX
const deltaY = touch.clientY - this.initY
// 计算新的位置
const style = window.getComputedStyle(this.element)
// WebKitCSSMatrix是用于操作矩阵的函数。m41就是translateX值,其中4代表第4列,1代表第一行。translateY的值,就用m42
const matrix = new WebKitCSSMatrix(style.transform)
let newX = matrix.m41 + deltaX,
newY = matrix.m42 + deltaY
// 定义安全边界(可以根据需要调整)
const safeMarginX = this.elementW / 3,
safeMarginY = this.elementH / 3 // 安全边界大小
// 确保元素不会移出窗口边界
newX = Math.min(Math.max(safeMarginX - this.elementW, newX), this.elementW - safeMarginX)
newY = Math.min(Math.max(safeMarginY - this.elementH, newY), this.elementH - safeMarginY)
// 应用平移(同时保留当前的缩放比例)
this.element.style.transform = `translate(${newX}px, ${newY}px) scale(${this.scale})`
// 平移结束后更新初始坐标
this.initX = touch.clientX
this.initY = touch.clientY
}
// 缩放
private zoom(event: TouchEvent) {
// 计算两点间的距离
const distance = this.getDistance(event)
if (this.lastDistance) {
const scaleChange = distance / this.lastDistance
// 计算新的缩放比例时基于初始缩放比例
const newScale = Math.min(Math.max(this.scale * scaleChange, this.minScale), this.maxScale)
// 更新缩放比例
this.scale = newScale
// 应用缩放
const style = window.getComputedStyle(this.element)
const matrix = new WebKitCSSMatrix(style.transform)
this.element.style.transform = `translate(${matrix.m41}px, ${matrix.m42}px) scale(${this.scale})`
}
// 更新距离用于下一次计算
this.lastDistance = distance
}
// 计算两点间的距离
private getDistance(evt: TouchEvent) {
const dx = evt.touches[0].clientX - evt.touches[1].clientX
const dy = evt.touches[0].clientY - evt.touches[1].clientY
return Math.sqrt(dx * dx + dy * dy)
}
}
export default Gesture