先把代码放上来
js逻辑代码
图标移动开始事件
start(e) {
//记录移动触摸起点位置
this.setData({
x: e.touches[0].clientX,
y: e.touches[0].clientY,
iconIndex: e.currentTarget.dataset.index
})
},
//图标移动中事件
move(e) {
if (flag) {
flag = false;
setTimeout(() => {
flag = true;
}, 100)
let arr = Object.assign({}, this.data.images, {})
//计算移动的距离
arr[e.currentTarget.dataset.index].position = {
left: e.touches[0].clientX - this.data.x,
top: e.touches[0].clientY - this.data.y
}
//这里是因为页面图片是遍历 images数组动态生成的,所以要修改images的值页面才会重新渲染,根据自身情况决定
this.setData({
images: arr
})
}
},
//图标移动结束
end(e) {
let arr = Object.assign({}, this.data.images, {})
this.data.imgUrl[this.data.imgIndex].props[e.currentTarget.dataset.index].left = arr[e.currentTarget.dataset.index].left = arr[e.currentTarget.dataset.index].left + arr[e.currentTarget.dataset.index].position.left;
this.data.imgUrl[this.data.imgIndex].props[e.currentTarget.dataset.index].top = arr[e.currentTarget.dataset.index].top = arr[e.currentTarget.dataset.index].top + arr[e.currentTarget.dataset.index].position.top;
arr[e.currentTarget.dataset.index].position = {
left: 0,
top: 0
};
this.setData({
images: arr
})
},
//图标缩放,旋转开始
scaleStart(e) {
let p = 500/this.data.imgUrl[this.data.imgIndex].width;//这是为了计算图片的原始尺寸,可忽略
x1 = ((125 + this.data.imgUrl[this.data.imgIndex].left * p + this.data.imgUrl[this.data.imgIndex].areaWidth / 2 * p) * this.data.p) + this.data.images[e.currentTarget.dataset.index].left;
y1 = ((102 + this.data.imgUrl[this.data.imgIndex].top * p + this.data.imgUrl[this.data.imgIndex].areaHeight / 2 * p) * this.data.p) + this.data.images[e.currentTarget.dataset.index].top;
//x1、y1是旋转或者缩放时图片的中心点坐标
let x = e.touches[0].clientX - x1,
y = e.touches[0].clientY - y1,
s = 0;
let cos = Math.abs(x) / Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5);
var radina = Math.acos(cos);
var angle = Math.floor(180 / (Math.PI / radina));
if (x > 0) {
if (y > 0) {
angle = 360 - angle
}
} else {
if (y > 0) {
angle += 180
} else {
angle = 180 - angle
}
}
//上面的代码是计算旋转或者缩放开始时触摸点和中心坐标与水平X轴的角度
this.setData({
actionIndex: e.currentTarget.dataset.index,
s: Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5),
deg1: angle
})
},
//缩放,旋转
scaleMove(e) {
if (flag) {
flag = false;
setTimeout(() => {
flag = true
}, 100)
//这个定时器是为了解决小程序中setData()使用频率太高导致代码阻塞,页面渲染延迟
let x = e.touches[0].clientX - x1,
y = e.touches[0].clientY - y1,
s = 0;
s = Math.pow((Math.pow(x, 2) + Math.pow(y, 2)), 0.5);
let cos = Math.abs(x) / s;
var radina = Math.acos(cos);
var angle = Math.floor(180 / (Math.PI / radina));
if (x > 0) {
if (y > 0) {
angle = 360 - angle
}
} else {
if (y > 0) {
angle += 180
} else {
angle = 180 - angle
}
}
//计算旋转或者缩放进行中触摸点和中心坐标与水平X轴的角度,从而得到图片的旋转角度
if (e.currentTarget.dataset.dragize !== 0) {
obj.scale = s / this.data.s.toFixed(2)
}
obj.rotate = parseInt(this.data.deg1 - angle)
this.setData(obj)
}
},
//图标缩放,旋转结束
scaleEnd(e) {
let arr = Object.assign({}, this.data.images, {});
this.data.imgUrl[this.data.imgIndex].props[e.currentTarget.dataset.index].scale = arr[e.currentTarget.dataset.index].scale = arr[e.currentTarget.dataset.index].scale * this.data.scale;
this.data.imgUrl[this.data.imgIndex].props[e.currentTarget.dataset.index].rotate = arr[e.currentTarget.dataset.index].rotate = arr[e.currentTarget.dataset.index].rotate + this.data.rotate;
this.setData({
images: arr,
actionIndex: -1,
rotate: 0,
scale: 1,
});
},
WXML页面代码
<view wx:for="{{images}}" wx:key="{{index}}" class='box {{index==iconIndex?"active":""}}' style='transform:translateX({{(item.left+item.position.left)/p}}rpx) translateY({{(item.top+item.position.top)/p}}rpx) rotateZ({{actionIndex==index?item.rotate+rotate:item.rotate}}deg) scale({{actionIndex==index?item.scale*scale:item.scale}}); left:{{imgUrl[imgIndex].areaWidth*500/imgUrl[imgIndex].width/2-(item.dragize==1?75:25)}}rpx;top:{{imgUrl[imgIndex].areaHeight/imgUrl[imgIndex].width*500/2-(item.dragize===1?75:25)}}rpx'
data-index='{{index}}'>
<image class='boxImg {{item.dragize==1?"":"BADGE"}}' catchtouchstart='start' catchtouchend='end' catchtouchmove="move" data-index="{{index}}" src='{{item.url}}?x-oss-process=image/resize,m_lfit,w_100'></image>
<view class='moveclose' style='transform:scale({{1/(actionIndex==index?item.scale*scale:item.scale)}})' hidden='{{index!=iconIndex}}' catchtap='moveclose' catchtouchmove data-index="{{index}}"></view>
<view class='movescale' style='transform:scale({{1/(actionIndex==index?item.scale*scale:item.scale)}})' hidden='{{index!=iconIndex}}' data-dragize='{{item.dragize}}' catchtouchmove="scaleMove" catchtouchstart="scaleStart" catchtouchend='scaleEnd' data-index='{{index}}'></view>
</view>
代码很乱。。毕竟是撸了三四天才搞出来的= =;哈哈哈,希望能有点帮助
最后把用到的数据结构分享一下
images: [{
dragize:1,//该图片是否允许缩放
height:960,//图片高度 初始值
id:41,
left:0,//图片的left值 相对于自己定义的初始位置
rotate:0,//旋转角度
scale:1,//缩放倍数
top:0,//图片的top值 相对于自己定义的初始位置
position:{
left:0,// 图片在移动过程中的偏移量
top:0// 图片在移动过程中的偏移量
}
url:"https://octopus-master.oss-cn-shenzhen.aliyuncs.com/sys/0fec4b1864b8341bb84d9216b2cc42df.png",
width:960//图片宽度 初始值
}],
iconIndex: -1, //大图中选中的图标下标
scale: 1, //缩放比例,图片在缩放过程中的倍数 缩放结束时应该用之前的倍数乘以该倍数
rotate: 0,//图片在旋转过程中的旋转角度 旋转结束时应该用之前的角度加上该角度
x: 0,
y: 0,
deg1: 0,
x1和y1我用的全局变量。。。因为只有在开始的时候赋值就可以后面不用改变