大家好,我是前端西瓜哥。最近文章比较少,因为在做个人开源项目,使用Canvas作为设计工具,制作乞丐版figma。这段时间遇到了很多问题,记录在这里。从今天开始,将恢复每隔一两天进行一次高频更新。内容会主要围绕我搭建的设计工具中遇到的一些问题和解决方案,也会有其他的话题。项目地址:https://github.com/F-star/suika在线体验:https://blog.fstars.wang/app/suika/元素及其包围盒(bBox)元素参考了一些图形,比如矩形,椭圆。为了描述方便,下面以矩形为例。元素有一个边界框(BoundingBox),它是可以包裹元素的最小矩形。当然大一点也可以,但是一定要能包住元素。constbBox={x:100,y:100,width:30,height:40}x和y表示边界框的位置,width和height表示框的大小。另外,元素有一个rotation属性,表示元素以其中心位置(即边界框的中心)为中心的旋转弧度。bBox被认为是旋转的(最外层的矩形):还有一个bBox不考虑旋转,我暂且称之为bBoxWithoutRotation。它会忽略旋转的存在,得到一个旋转前的bBox。我们将它与渲染层(ctx.rotate(angle))一起使用来绘制旋转框。bBoxWithoutRotation选中元素选中元素分两种情况需要讨论,一种是选中单个元素,另一种是选中多个元素。对于单个元素,绘制bBoxWithoutRotation。原因是只有一个元素,就是旋转角度,旋转更能表达这个元素的情况。见下图:对于多个元素,情况不同,因为不同的元素有不同的旋转角度,所以需要计算所有元素的bBox,然后取出最小的x,y和最大的x,y到形成一个包围所有Element的Checkbox的圆圈:RotatingElements旋转元素也分两种情况讨论:旋转单个元素和旋转多个元素。让我们从旋转单个元素开始。看效果:旋转单个元素首先,从图形的中点开始连接光标位置,得到一个向量。我们的旋转角度就是这个向量和向上向量的夹角(即[0,-1])。求矢量角度这里我们可以使用点积公式来计算角度。计算出夹角后,赋值给选中元素的旋转属性,然后渲染让渲染引擎按照新的角度绘制。然后有多个元素要旋转。效果:旋转多个元素旋转多个元素有点复杂。我们需要改变每个元素的旋转角度,以及x和y值。这里我们需要知道一个很重要的信息:元素上所有点的旋转结果坐标是根据大边界框的中心旋转得到的。首先是旋转,旋转的中心就是这个大bBox的中心。我们从元素的中点画一个向上的向量,这个向量随着多元素旋转角度的变化而变化。因此,与直接赋值单个元素不同,在多元素旋转的情况下,每次旋转前需要将拖动时产生的旋转角度作为增量加到元素的起始角度上,即:元素.rotation=prevElementRotation+dRotation;然后为每个元素计算新的x和y值。这也很简单。对于旋转前的中点cx和cy,用旋转算法计算出新的cx和cy,然后减去width/height/2。需要实现的算法这个过程中需要实现的算法是:求向量之间的夹角,需要用到点积公式。旋转算法需要考虑旋转中心。计算bBox其实就是将bBox转换成4个角的坐标,然后取最小的x,y和最大的x,y重新组合成一个盒子。那么剩下的就是繁琐的交互逻辑了。至此,我们实现了元素的旋转逻辑。稍后我将发布另一篇关于缩放元素的文章。
