您的当前位置:首页正文

小程序中图片的移动、旋转和缩放功能

2024-11-11 来源:个人技术集锦

先把代码放上来

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我用的全局变量。。。因为只有在开始的时候赋值就可以后面不用改变

显示全文