外层元素旋转,其包括在内的子元素一并旋转(不改变旋转中心),单元测试

思路:元素外层中心(坐标系中心)旋转后坐标,元素中心旋转后坐标,计算偏移坐标。
在这里插入图片描述

在这里插入图片描述

    中心点 cx: {{resize.x+resize.w/2}}, cy: {{resize.y+resize.h/2}}
    <br />
    <label>
      角度:
      <input v-model.number="rotate" type="number" step="30" />
    </label>
    <br />
    <label>
      x 平移:
      <input v-model.number="resize.x" type="number" @input="inputX" step="50" />
    </label>
    <br />
    <label>
      y 平移:
      <input v-model.number="resize.y" type="number" @input="inputY" step="50" />
    </label>
    <br />
    <div
      class="resizebox"
      :style="{
      width: `${resize.w}px`, 
      height: `${resize.h}px`, 
      transform: `translate(${resize.x}px, ${resize.y}px) rotate(${rotate}deg)`}"
    ></div>
    <div
      :class="['itxm', `itxm-${idx}`]"
      v-for="(item, idx) in points"
      :key="idx"
      :style="{
      width: `${item.w}px`, 
      height: `${item.h}px`, 
      transform: `translate(${item.x}px, ${item.y}px) rotate(${rotate}deg)`}"
    >{{idx+1}}</div>
     
  </div>
</template>
<script>
export default {
  name: 'resizeRect',
  data() {
    return {
      rotate: 15,
      rotateOld: 0,
      resize: {
        x: 200,
        y: 200,
        w: 500,
        h: 300,
        r: 0,
      },
      resizeOld: {
        x: 200,
        y: 200,
        w: 500,
        h: 300,
        r: 0,
      },
      points: [
        {
          x: 200,
          y: 200,
          w: 50,
          h: 30,
          r: 0,
        },
         {
          x: 650,
          y: 200,
          w: 50,
          h: 30,
          r: 0,
        },
        {
          x: 300,
          y: 300,
          w: 50,
          h: 30,
          r: 0,
        },
        {
          x: 200,
          y: 470,
          w: 50,
          h: 30,
          r: 0,
        },
        {
          x: 650,
          y: 470,
          w: 50,
          h: 30,
          r: 0,
        },
      ],
      rangex: 0,
      rangey: 0,
    };
  },
  watch: {
    rotate() {
      this.watchRotate();
    },
  },
  mounted() {
    this.watchRotate();
  },
  methods: {
    watchRotate() {
      const cx = this.resize.x + this.resize.w / 2;
      const cy = this.resize.y + this.resize.h / 2;
      const rotateRange = this.rotate - this.rotateOld;
      this.points.forEach((v) => {
        console.log(JSON.parse(JSON.stringify(v)));
        if (!v.oldx) v.oldx = v.x;
        if (!v.oldy) v.oldy = v.y;
        // resize旋转为矩形参考
        const rotateEnd = this.recaculateXY({ x: v.oldx, y: v.oldy, cx, cy, rotate: rotateRange });
        // v.x + v.w / 2 , v.y + v.h / 2,  自身坐标需要勾股计算,这里暂时用 除 2
        const rotateThis = this.recaculateXY({ x: v.x, y: v.y, cx: v.x + v.w / 2, cy: v.y + v.h / 2, rotate: rotateRange });
        // 外层旋转坐标偏移 - 自身旋转坐标偏移
        const rangex = rotateEnd.x - rotateThis.x
        const rangey = rotateEnd.y - rotateThis.y 
        v.x += rangex;
        v.y += rangey;
        v.oldx  = v.x
        v.oldy  = v.y
      });
      this.rotateOld = this.rotate;
    },
    recaculateXY({ x, y, cx, cy, rotate }) {
      // 矩阵公式
      const rad = (rotate * Math.PI) / 180;
      const rotatedX = (x - cx) * Math.cos(rad) - (y - cy) * Math.sin(rad) + cx;
      const rotatedY = (x - cx) * Math.sin(rad) + (y - cy) * Math.cos(rad) + cy;
      return { x: rotatedX, y: rotatedY };
    },
    inputY() {
      const range = this.resize.y - this.resizeOld.y;
      console.log(range);
      this.rangey = range;
      this.points.forEach((v) => {
        v.y += range;
        v.oldy = v.y;
      });
      this.resizeOld = JSON.parse(JSON.stringify(this.resize));
    },
    inputX() {
      const range = this.resize.x - this.resizeOld.x;
      console.log(range);
      
      this.rangex = range;
      this.points.forEach((v) => {
        v.x += range;
        v.oldx = v.x;
      });
      this.resizeOld = JSON.parse(JSON.stringify(this.resize));
    },
  },
};
</script>

<style scoped>
.outbox {
  position: relative;
}
.resizebox {
  width: 500px;
  height: 300px;
  border: 2px dotted blue;
  position: absolute;
  left: 0;
  top: 0;
  &::after {
    content: '';
    width: 100%;
    height: 1px;
    background: red;
    display: block;
    position: absolute;
    top: 50%;
  }
  &::before {
    content: '';
    width: 1px;
    height: 100%;
    background: red;
    display: block;
    position: absolute;
    left: 50%;
  }
}
.resizebox2 {
  border: 1px solid black;
}
.itxm {
  background: green;
  position: absolute;
  left: 0;
  top: 0;
}
.itxm-1 {
  background: orange;
}
.itxm-2 {
  background: rebeccapurple;
}
</style>

–end

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值