low-code相关1 | 青训营笔记

108 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第7天

本文主要记录低代码项目的学习📖 本期讨论有关组件的旋转遇到的问题

旋转

旋转是低代码一个难点 因为需要考虑的东西很多

  • 要计算旋转的角度

  • 旋转后光标也要改变

  • 旋转后组件的放大缩小模式可能由于光标的改变而变

旋转角度

通过查阅资料 🔍大概总结如下📃

首先介绍一个函数📐

Math.atan2() 是JavaScript数学库中的函数,用于查找其参数商的反正切。 Math.atan2(y,x) 将返回作为(x,y)点和x轴角度的数值。
❗注意

  • 第一个参数是y,第二个参数是x

  • 算出来是弧度 要转换为角度 即除以Math.PI/180

我们以组件中心点为原点 那么我们要做的是

  • 提前计算出组件中心点centerXcenterY,因为不会随着旋转而改变 记录一开始的旋转角度rotate
  • 鼠标点击时计算出 对应的x、y 假设为startXstartY 同时利用公式计算点击时的角度 如下 const startRotate = Math.atan2(startY - centerY, startX - centerX)/(Math.PI/180)
  • 鼠标移动时利用公式计算出实时的角度 如下
    const curRotate = Math.atan2(curY - centerY, curX - centerX)/(Math.PI/180)
  • 计算出最终 style.rotate = rotate+(curRotate -startRotate)
  • 注意 ❗ 只改变轮廓的transform即可 若父子元素都改变会产生叠加导致子元素旋转两倍 如下图

1.gif

旋转后的缩放

做到这里 已经可以实现旋转了 但是会发现 缩放出现了bug

这是因为 🤔

  • 外框的八个点对应的光标被写死

  • 每个光标对应的缩放模式被写死

旋转时中心点不变 故先计算出中心点的坐标

要计算几个重要点的坐标📍

按下鼠标时计算中心点

const center = {
    x:style.left + style.width/2,
    y:style.top + style.height/2
}

对称点

//当前点击坐标
const startPoint = {
    x:e.clientX - rect.left,
    y:e.clientY - rect.top
}
​
//对称点
const symmetricPoint = {
        x:center.x - (startPoint.x-center.x),
        y:center.y - (startPoint.y-center.y)
      }
 const move = function (ev) {
        //移动中的当前坐标
        const curPoint = {
          x:ev.clientX - left,
          y:ev.clientY - top
        }
​
        //计算新的中心点
        // const newCenter = centerPoint(curPoint,symmetryPoint)
        calcTL(style,curPoint,{symmetricPoint,pointType:i})
​
      }

由于组件旋转过程中 top left 宽高都没改变 故缩放其实是在组件带着对应角度的transform属性下去改变其宽高或top、left

由于中心点不变 实际上 在已旋转状态下缩放 可以 等价为 在没旋转时缩放后再旋转

因此 我们需要利用当前鼠标位置(旋转状态) 及中心点(旋转不变)、 旋转角度 得出 对应的新坐标(没旋转的)

利用当前鼠标位置的对称点(旋转状态) 及中心点(旋转不变)、 旋转角度 得出 对应的新坐标的对称点(没旋转的)

// 计算新top、left
function calcTL(style,curPoint,pointInfo) {
    const {symmetricPoint,pointType } = pointInfo  // 对称点
    const newCenterPoint = centerPoint(curPoint,symmetricPoint)// 得到新的中心点
    const newTL = calcRotate(curPoint,newCenterPoint,-style.rotate) // 新的左上角坐标
    const newBR = calcRotate(symmetricPoint,newCenterPoint,-style.rotate)// 新的右下角坐标
    
    // 计算新宽高
    const width = newBR.x - newTL.x 
    const height = newBR.y - newTL.y
    console.log(typeof(-height));
    if (pointType.includes("t")) {
        style.height = height
        style.top = newTL.y
      }
      if (pointType.includes("b")) {
        style.height = -height
      }
      if (pointType.includes("l")) {
        style.left = newTL.x
        style.width = width
      }
      if (pointType.includes("r")) {
        style.width = -width
        
      }
​
}

光标问题

  • 给8个点分别设置初始光标对应角度 如下
const initialAngle = {
  // 每个点对应的初始角度
  lt: 0,
  t: 45,
  rt: 90,
  r: 135,
  rb: 180,
  b: 225,
  lb: 270,
  l: 315,
};
  • 规定不同角度对应什么光标 如下
const angleToCursor = [
  { start: 338, end: 23, cursor: "nw" },
  { start: 23, end: 68, cursor: "n" },
  { start: 68, end: 113, cursor: "ne" },
  { start: 113, end: 158, cursor: "e" },
  { start: 158, end: 203, cursor: "se" },
  { start: 203, end: 248, cursor: "s" },
  { start: 248, end: 293, cursor: "sw" },
  { start: 293, end: 338, cursor: "w" },
];
  • 根据角度给予对应的光标
//角度计算方法  角度 = 旋转角度 + 初始光标的角度
const angle = style.rotate + initialAngle[pointType]

💭💭💭

记录低代码项目中的问题📜
若本文对你有帮助 欢迎点赞收藏👍📑
若有纰漏,敬请包涵,评论区欢迎指正👂