前言
本文分析怎么在微信小程序实现双指缩放图片的功能。
实现过程
1. 文件index.wxml和index.wxss代码如下,这一块比较简单,可自行查看,不做过多分析;
<!--index.wxml-->
<view class='wrapper'>
<view class="container">
<view class="title">双指缩放图片</view>
<scroll-view class='images' scroll-y="true" scroll-x="true" bindtouchmove="touchmoveCallback" bindtouchstart="touchstartCallback">
<image mode="aspectFit" src="../../images/big.jpg" style="width:{
{scaleWidth }}px;height:{
{scaleHeight}}px" bindload="imgload"></image>
<!-- <image mode="aspectFit" src="../../images/small.jpg" style="width:{
{scaleWidth }}px;height:{
{scaleHeight}}px" bindload="imgload"></image> -->
</scroll-view>
</view>
</view>
/**index.wxss**/
.container {
margin-top: 30rpx;
}
.container .title {
margin-bottom: 20rpx;
font-weight: bold;
}
2. 文件index.js存放所有功能的逻辑代码,主要思路是先计算触摸时双指的距离(distance),然后计算移动过程的双指距离并跟触摸时的距离的差值(distanceDiff)来计算缩放比例(newScale),最后用计算出的缩放比例来缩放图片(scaleWidth和scaleHeight);代码实现如下:
1)新建公共方法calcDistance,用来计算双指的距离;
2)新建方法imgload,当图片载入完毕时获取图片实际宽度(baseWidth)和高度(baseHeight)、用来计算的固定宽度(initWidth,原图宽度大于屏幕宽度则设置为屏幕宽度,反之则设置为原图宽度)和高度(initHeight,原图宽度大于屏幕宽度则设置为原图高度/倍数,反之则设置为原图高度)、图片缩放后的宽度(scaleWidth,初始化跟initWidth一致)和高度(scaleHeight,初始化跟initHeight一致);
3)新建方法touchstartCallback,计算双指触摸时双指的距离distance;
4)新建方法touchmoveCallback,计算手指移动时双指的距离distance,跟触摸距离相减得出差值distanceDiff;然后利用差值计算出缩放比例newScale,最后使用newScale缩放图片,从而实现缩放效果。
//index.js
Page({
/**
* 页面的初始数据
*/
data: {
distance: 0, // 手指移动的距离
scale: 1, // 缩放比例
baseWidth: '', // 图片实际宽度
baseHeight: '', // 图片实际高度
initWidth: '', // 图片默认显示宽度
initHeight: '', // 图片默认显示高度
scaleWidth: '', // 图片缩放后的宽度
scaleHeight: '', // 图片缩放后的高度
},
/**
* 监听图片加载成功时触发
*/
imgload: function (e) {
this.multiple = e.detail.width / this.width; // 计算原图和默认显示的倍数
let height = this.multiple > 1 ? e.detail.height / this.multiple : e.detail.height; // 等比例计算出默认高度
let width = this.multiple > 1 ? this.width : e.detail.width;
this.setData({
baseWidth: e.detail.width, // 获取图片实际宽度
baseHeight: e.detail.height, // 获取图片实际高度
initWidth: width,
initHeight: height,
scaleWidth: width,
scaleHeight: height,
})
},
/**
* 双手指触发开始 计算开始触发两个手指坐标的距离
*/
touchstartCallback: function (e) {
// 单手指缩放开始,不做任何处理
if (e.touches.length == 1) return;
let distance = this.calcDistance(e.touches[0], e.touches[1]);
this.setData({
'distance': distance,
})
},
/**
* 双手指移动 计算两个手指坐标和距离
*/
touchmoveCallback: function (e) {
// 单手指缩放不做任何操作
if (e.touches.length == 1) return;
let distance = this.calcDistance(e.touches[0], e.touches[1]);
// 计算移动的过程中实际移动了多少的距离
let distanceDiff = distance - this.data.distance;
let newScale = this.data.scale + 0.005 * distanceDiff;
if (newScale >= this.multiple && this.multiple > 2) { // 原图比较大情况
newScale = this.multiple;
} else if (this.multiple < 2 && newScale >= 2) { // 原图较小情况
newScale = 2; // 最大2倍
};
// 最小缩放到0.3
if (newScale <= 0.3) {
newScale = 0.3;
};
let scaleWidth = newScale * this.data.initWidth;
let scaleHeight = newScale * this.data.initHeight;
this.setData({
distance: distance,
scale: newScale,
scaleWidth: scaleWidth,
scaleHeight: scaleHeight,
diff: distanceDiff
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 获取屏幕宽度
this.width = wx.getSystemInfoSync().windowWidth;
},
/**
* 计算两个手指距离
*/
calcDistance(pos0, pos1) {
let xMove = pos1.clientX - pos0.clientX;
let yMove = pos1.clientY - pos0.clientY;
return (Math.sqrt(xMove * xMove + yMove * yMove));
}
})
扫描公众号,了解更多实例分享: