小程序 当整个组件或者页面transform scale(n)的时候,拖拽 旋转拉伸事件的

<view disable-scroll="{{true}}"  catchTap="changeItem" class="photo-item  {{!itemInfo.selectEnabled?'noPointer':''}}" style=" transform: rotate({{itemStyle.rotate}}deg);width:{{itemStyle.width}};height:{{itemStyle.height}};left:{{itemStyle.x}};top:{{itemStyle.y}};background:{{bgColor?bgColor:''}};{{changeIdx == idx?'border :2px dashed rgb(255, 76, 136)':''}}" 
  a:if="{{itemInfo.visible &&imgUrl}}">
  <image mode="scaleToFill" src="{{imgUrl}}" style="width:100%;height:100%" onTouchStart="handleTouchStart" onTouchMove="handleTouchMove" 
    onTouchEnd="handleTouchEnd" />
  <view a:if="{{changeIdx == idx}}" class="control-point-left" catchTap="handledelitem">
    <image style="width:100%;height:100%;" mode="scaleToFill" src="../../../../assets/imgs/del.png" />
    
  </view>
  <view a:if="{{changeIdx == idx}}" class="control-point-right" onTouchStart="handleControlPointStart" onTouchMove="handleControlPointMove" 
    onTouchEnd="handleControlPointEnd">
    <image style="width:100%;height:100%;" mode="scaleToFill" src="../../../../assets/imgs/rotate.png" />
  </view>
</view>

上面是大概的页面是我的小贴纸



Component({
  mixins: [],
  data: {
    itemStyle: {
      width: 0,
      height: 0,
      rotate: 0,
      x: 0,
      y: 0
    },
    media: {},
    bgColor: '',
    delX: 0,
    delY: 0,
    bigx: 0,
    bigy: 0,
    changeIdx: 0,
    startX: 0,
    startY: 0,
    originalX: 0,
    originalY: 0,

    controlPoint: {
      startX: 0, // 控制点触摸起始X坐标
      startY: 0, // 控制点触摸起始Y坐标
      startWidth: 0, // 图片初始宽度
      startHeight: 0, // 图片初始高度
      startRotate: 0, // 图片初始旋转角度
      startCenterX: 0, // 图片中心点X坐标
      startCenterY: 0, // 图片中心点Y坐标
      startScaleFactor: 1
    },
    currentX: 0,
    currentY: 0,


  },
  props: {
    itemInfo: Object,
    changeIdx: Number,  // 当前选中的图层索引
    idx: Number,       // 当前组件索引
    cachedOffsetLeft: Number,
    cachedOffsetTop: Number,
    onSaveInfo: () => Void,
    onDelItem: () => Void,
  },
  didMount() {
    this.initUi();
    // this.cacheElementPosition();
  },
  didUpdate() {
    if (this.props.itemInfo && JSON.stringify(this.props.itemInfo) !== JSON.stringify(this.data.itemInfo)) {
      this.setData({
        itemInfo: this.props.itemInfo
      });
      this.initUi();
    }
    if (this.props.changeIdx !== this.data.changeIdx) {
      this.setData({
        itemInfo: this.props.itemInfo,
        changeIdx: this.props.changeIdx,
        bigx: this.data.itemInfo.location.x,
        bigy: this.data.itemInfo.location.y,
      });

    }
  },
  didUnmount() { },
  methods: {
   


    initUi() {
      let { itemInfo } = this.props;
      let { media, location, visible } = itemInfo;
      let { imgPath } = media
      let { width, height, x, y, rotation } = location;

      let imgUrl = '';
      if (visible && imgPath) {
        if (imgPath.startsWith("MXYZ-")) {
          imgUrl = 'https://ddiy.36588.com.cn/image/server/mongo_yx/' + imgPath;
        } else {
          imgUrl = 'https://ddiy.36588.com.cn/image/server/fs1020/' + imgPath;
        }
      }
      this.setData({
        itemStyle: {
          width: width,
          height: height,
          x: x,
          y: y,
          rotate: rotation
        },
        imgUrl,
        bigx: x,
        bigy: y,
      })
    },
    changeItem() {
      this.props.onChangeIdx(this.props.idx)
      this.setData({
        bigx: this.data.itemInfo.location.x,
        bigy: this.data.itemInfo.location.y,
      });

    },
    handleTouchStart(e) {
      if (this.props.idx !== this.props.changeIdx) return;

      // Record the initial touch position and current item position
      this.setData({
        startX: e.touches[0].clientX,
        startY: e.touches[0].clientY,
        originalX: this.data.itemStyle.x,
        originalY: this.data.itemStyle.y
      });
    },

    handleTouchMove(e) {
      if (this.props.idx !== this.props.changeIdx) return;

      // Calculate the distance moved
      const deltaX = e.touches[0].clientX - this.data.startX;
      const deltaY = e.touches[0].clientY - this.data.startY;

      // Apply the movement with scale consideration
      const scaleFactor = 1 + (this.props.demoStyle.scale || 0);
      const newX = this.data.originalX + deltaX * scaleFactor;
      const newY = this.data.originalY + deltaY * scaleFactor;

      this.setData({
        'itemStyle.x': newX,
        'itemStyle.y': newY,
        bigx: newX,
        bigy: newY
      });
    },

    handleTouchEnd(e) {
      if (this.props.idx !== this.props.changeIdx) return;

      // Save the final position
      const info = JSON.parse(JSON.stringify(this.data.itemInfo));
      info.location.x = this.data.itemStyle.x;
      info.location.y = this.data.itemStyle.y;
      info.location.width = this.data.itemStyle.width;
      info.location.height = this.data.itemStyle.height;
      info.printLocation.x = this.data.itemStyle.x;
      info.printLocation.y = this.data.itemStyle.y;
      info.printLocation.width = this.data.itemStyle.width;
      info.printLocation.height = this.data.itemStyle.height;
      this.props.onSaveInfo(info);
    },

    // 右下角控制点位aa
    handleControlPointStart(e) {

      const touch = e.touches[0];
      const { x, y, width, height, rotate } = this.data.itemStyle;
      const parentScale = this.props.demoStyle.scale || 1; // 获取父元素缩放比例,默认为1

      // 计算图片中心点坐标(考虑父元素缩放)
      const centerX = x + width / 2;
      const centerY = y + height / 2;
      // 使用缓存的偏移量
      const offsetLeft = this.props.cachedOffsetLeft;
      const offsetTop = this.props.cachedOffsetTop;

      // 计算触摸点相对于中心点的位置(考虑父元素缩放)
      const touchX = (touch.clientX - offsetLeft) / parentScale;
      const touchY = (touch.clientY - offsetTop) / parentScale;

      this.setData({
        controlPoint: {
          startX: touchX,
          startY: touchY,
          startWidth: width,
          startHeight: height,
          startRotate: rotate,
          startCenterX: centerX,
          startCenterY: centerY,
          parentScale: parentScale,
          startDistance: Math.sqrt(
            Math.pow(touchX - centerX, 2) +
            Math.pow(touchY - centerY, 2)
          )
        }
      });
    },

    // 处理旋转和缩放
    handleControlPointMove(e) {
      if (this.props.idx !== this.props.changeIdx) return;

      const touch = e.touches[0];
      const { controlPoint, itemStyle } = this.data;
      const parentScale = controlPoint.parentScale || 1;
    
      // 计算当前触摸点位置(考虑父元素缩放和页面滚动)
      const currentX = (touch.clientX - this.props.cachedOffsetLeft) / parentScale;
      const currentY = (touch.clientY - this.props.cachedOffsetTop) / parentScale;

      // 计算旋转角度
      const deltaX = currentX - controlPoint.startCenterX;
      const deltaY = currentY - controlPoint.startCenterY;
      const startDeltaX = controlPoint.startX - controlPoint.startCenterX;
      const startDeltaY = controlPoint.startY - controlPoint.startCenterY;

      // 计算当前角度和初始角度
      const currentAngle = Math.atan2(deltaY, deltaX) * 180 / Math.PI;
      const startAngle = Math.atan2(startDeltaY, startDeltaX) * 180 / Math.PI;

      // 计算角度变化(保持在0-360度范围内)
      let angleDelta = currentAngle - startAngle;
      angleDelta = ((angleDelta + 180) % 360) - 180; // 限制在-180到180度之间

      // 计算新旋转角度(考虑旋转限制)
      let newRotate = controlPoint.startRotate + angleDelta;

      // 限制旋转角度在0-360度之间
      newRotate = (newRotate % 360 + 360) % 360;

      // 计算缩放比例
      const currentDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
      const scale = currentDistance / controlPoint.startDistance;

      // 限制最小和最大缩放比例
      const minScale = 0.1;
      const maxScale = 5;
      const effectiveScale = Math.min(maxScale, Math.max(minScale, scale));

      // 计算新尺寸
      const newWidth = controlPoint.startWidth * effectiveScale;
      const newHeight = controlPoint.startHeight * effectiveScale;

      // 更新图片数据(保持中心点不变)
      const newX = controlPoint.startCenterX - newWidth / 2;
      const newY = controlPoint.startCenterY - newHeight / 2;

      this.setData({
        itemStyle: {
          ...itemStyle,
          width: newWidth,
          height: newHeight,
          rotate: newRotate,
          x: newX,
          y: newY
        }
      });
    },


    handleControlPointEnd(e) {
      if (this.props.idx !== this.props.changeIdx) return;

      // 保存最终状态(这部分不变)
      const info = JSON.parse(JSON.stringify(this.data.itemInfo));
      info.location.x = this.data.itemStyle.x;
      info.location.y = this.data.itemStyle.y;
      info.location.width = this.data.itemStyle.width;
      info.location.height = this.data.itemStyle.height;
      info.location.rotation = this.data.itemStyle.rotate;
      info.printLocation.x = this.data.itemStyle.x;
      info.printLocation.y = this.data.itemStyle.y;
      info.printLocation.width = this.data.itemStyle.width;
      info.printLocation.height = this.data.itemStyle.height;
      info.printLocation.rotation = this.data.itemStyle.rotate;
      this.props.onSaveInfo(info);
    },

    handledelitem() {
      // this.props.onChangeIdx(this.props.idx)
      this.props.onDelItem(this.props.idx)
    }
  },
});

这是js 代码,自己看吧哈哈哈,重点是 :

 // 计算当前触摸点位置(考虑父元素缩放和页面滚动)
      const currentX = (touch.clientX - this.props.cachedOffsetLeft) / parentScale;
      const currentY = (touch.clientY - this.props.cachedOffsetTop) / parentScale;

这里面的 this.props.cachedOffsetLeft   this.props.cachedOffsetTop    是获取你的画布的位置,下面是代码

 my.createSelectorQuery()
        .select('.templateDemo')
        .boundingClientRect()
        .exec((ret) => {
          if (ret && ret[0]) {
            this.setData({
              cachedOffsetLeft: ret[0].left,
              cachedOffsetTop: ret[0].top
            });
          }
        });

嘻嘻嘻,开心!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值