微信小程序,从0到1实现图片的双指缩放和单指移动功能的代码分享
一、当手指触摸图片后,图片以全屏形式在手机上显示出来,就是调用了这段代码。
dealWithPicScale(picUrl) 方法做了两件事:
1、接收图片 url,并设置给 image 标签的 src 属性(这里用的微信小程序的 this.setData()方法实现页面渲染,如果要用其他框架,那就改成对应框架的方法)。
2、获取图片实际的尺寸比例,后面缩放图片时会用到。
picSizeRatio (图片尺寸比例,在缩放图片时会用到),
dealWithPicScale(picUrl){
this.setData({
picUrl: picUrl,
picHidden: false
})
wx.getImageInfo({
src: picUrl,
success: (res)=>{
this.picSizeRatio = Math.floor(res.height / res.width);
}
})
},
二、图片全屏显示后,接下来会触摸图片,这就是触摸图片后触发的事件方法。
(historyX ,historyY), 记录触摸屏幕的实际坐标,记录这个坐标的原因是手指在屏幕上滑动时会先触发该事件,后触发手指移动的事件,正好记录下手动滑动屏幕的起始点,后面计算滑动距离时会用到该坐标值。
picTapped(res) 方法做了两件事:
1、记录该事件触发的状态。
2、记录记录手指触摸屏幕的 x y 坐标。
picTapped(res){
this.data.eventState.clicked = true; // 设置状态为 true,表示该事件已触发了
const touches = res.touches;
this.data.eventState.historyX = Math.floor(touches[0].pageX);
this.data.eventState.historyY = Math.floor(touches[0].pageY);
// console.log("图片点击了")
// console.log(res)
},
三、手指在屏幕上滑动时会触发的事件方法
(eventState.x,eventState.y),记录手指在屏幕上滑动的轨迹,然后赋值给四个 pageXXX 参数。这里出现 “单指移动” 和 “双指缩放” 两种情况,在这里做了分支处理(单指移动需要两个参数,双指需要四个)。
picMoved(res) 方法做了两件事:
1、记录手指在屏幕上滑动的轨迹。
2、区分出是 “单指” 还是 “双指” 事件,收集相应参数做分支处理。
picMoved(res){
this.data.eventState.moved = true; // 设置为 true, 表示手指滑动事件触发了
const touches = res.touches;
this.data.eventState.x = Math.floor(touches[0].pageX);
this.data.eventState.y = Math.floor(touches[0].pageY);
let pageX1;
let pageY1;
let pageX2;
let pageY2;
if(touches.length > 1){
for(let i = 0; i
p // 双指与单指间会出现串扰,通过该值判断并消除串扰/p p const doubleTap = this.data.eventState.doubleTap; /p p const pWidth = this.picWidth; // 收集图片宽/p p const pHeight = this.picHeight; // 收集图片高/p p const screenHeight = wx.getSystemInfoSync().windowHeight; // 拾取手机屏幕的高度/p p const screenWidth = wx.getSystemInfoSync().windowWidth; // 拾取手机屏幕的宽度/p p // 消除串扰所做的判断/p p if(doubleTap == 0){ /p p // 判断图片的宽度是否超过手机屏幕的宽度或高度,如果超过了,说明图片被缩放了/p p if(pWidth > screenWidth || pHeight > screenHeight){// 收集移动的终点 x 坐标与移动起点 x 坐标之差,用于决定横向移动距离和方向
const width = pageX1 - this.data.eventState.historyX;
// 收集移动的终点 y 坐标与移动起点 y 坐标之差,用于决定纵向移动距离和方向
const height = pageY1 - this.data.eventState.historyY;
// left, top 记录的是图片元素相对于父元素的偏移量(对应于 margin-left 和 margin-top)
// 这里的数值 1.5 是为了加快移动的速度,这个值可根据个人喜好来修改
// tempWidth,tempHeight , 就是计算出的实际要移动图片的距离了
let tempWidth = this.data.eventState.left + Math.round(width * 1.5);
let tempHeight = this.data.eventState.top + Math.round(height * 1.5);
// screenWidth - pWidth 之差决定了图片横向移动的最大距离
// screenHeight - pHeight 之差决定了图片纵向能移动的最大距离
const maxLeft = screenWidth - pWidth;
const maxHeight = screenHeight - pHeight;
// width > 0,说明图片向右移动
if(width > 0){
// tempWidth > 0,说明图片向右移动到极限位置,此时的 margin-left 最值应赋 0
// tempWidth 就是用于设置 margin-left 的
if(tempWidth > 0){
tempWidth = 0;
}
}else{
// tempWidth
p tempWidth = maxLeft;/p p }/p p }/p p // height 0,说明是在向下移动/p p if(height > 0){// tempHeight > 0,说明图片向下移动到了极限位置,此时 margin-top 应赋 0
if(tempHeight > 0){
tempHeight = 0;
}
}else{
// tempHeight
p middleX = Math.floor((pageX1 + pageX2) / 2);/p p middleY = Math.floor((pageY1 + pageY2) / 2);/p p// 下面的赋值可能是冗余,笔者懒得去思考了,留给你们/p p this.data.eventState.middleX = middleX;/p p this.data.eventState.middleY = middleY;/p p }/p p// result = distance2 - distance1,用于确定是放大还是缩小图片的事件/p p// result 0,说明是放大图片/p p if(result > 0){// picWidth 大于 960个像素时,就赋予极限值 960,该值可根据个人喜好修改
if(picWidth >= 960){
picWidth = 960;
left = tempLeft;
top = tempTop;
}else{
// 如果图片宽度在 960 以内,就以图片宽高加上 widthSize, heightSize 的值放大图片
picWidth = picWidth + widthSize;
picHeight = picHeight + heightSize;
// 下面这些代码就是在修改 left,top 的值,目的就是为了在缩放图片时能以双指间的中心点
// 为原点来缩放图片,是基于前面将屏幕横向 7 等份,纵向 5 等份划分后的操作,即将屏幕划分
// 出了 35 个像素块, 中心点落在其中某个块后,就对应的修改 left,top 的大小,达到以中心点为
// 原点的缩放效果
if(middleX
p left = tempLeft - leftSize;/p p }else if(middleX > lPiece && middleX p left = tempLeft - leftSize * 2;/p p }else if(middleX > lPiece * 2 && middleX p left = tempLeft - leftSize * 3;/p p }else if(middleX > lPiece * 3 && middleX p left = tempLeft - leftSize * 4;/p p }else if(middleX > lPiece * 4 && middleX p if(left > 0 && top > 0){left = left - 1;
top = top - 1;
}
if(left