大家好,我是前端西瓜哥。
今天我们来研究一下 Figma 是如何表示图形的,这里以矩形为切入点进行研究。
明白最简单的矩形的表示后,研究其他的图形就可以举一反三。
矩形的一般表达
如果让我设计一个矩形图形的物理属性,我会怎么设计?
我张口就来:x、y、width、height、rotation。
对一些简单的图形编辑操作,这些属性基本上是够用的,比如白板工具,如果你不考虑或者不希望图形可以翻转(flip) 的话。
Figma 需要考虑翻转的情况的,此外还有斜切的情况。
翻转的场景:
还有斜切的场景,在选中多个图形然后缩放时有发生。
这些表达光靠上面的几个属性是不够的,我们看看 Figma为了表达这些效果,是怎么去设计矩形的。
Figma 矩形物理属性
与物理信息相关的属性如下:
没有位置属性,这个属性默认是 (0, 0),实际它转移到 transform 的矩阵的位移子矩阵上了。
size 表示宽高,但属性名用的是 x(宽) 和 y(高),理论上 width 和 height 语义更好,这样应该是用了矢量类型。
size 表示宽高,理论上 width 和 height 语义更好,这样应该是用了平面矢量类型的结构体,所以是 x 和 y。
transform 表示一个 3x3 的变换矩阵。
上面的 transform 属性的值所对应的矩阵为:
属性面板
再看看这些属性对应的右侧属性面板。
x、y 分别是 5 和 6,它是 (0, 0) 进行 transform 后的结果,这个直接对应 transform.m02 和 tansfrom.m12。
这里引入了 pixi.js 的 matrix 类,该类使用列向量方式进行表达。
文末有 demo 源码以及线上 demo,可打开控制台查看结果验证正确性。
然后这里的 width 和 height,是 223.61 和 500, 怎么来的?
它们对应的是矩形的两条边变形后的长度,如下:
uiWidth 为 (0, 0) 和 (width, 0) 进行矩阵变换后坐标点之间的距离。
最后计算出 223.60679774997897,四舍五入得到 223.61。
高度计算同理。
uiHeight 为 (0, 0) 和 (0, height) 进行矩阵变换后坐标点之间的距离。
旋转角度
最后是旋转角度,它是宽度对应的矩形边向量,逆时针旋转 90 度的向量所对应的角度。
先计算宽边向量,然后逆时针旋转 90 度得到旋转向量,最后计算旋转向量对应的角度。
这里用了几个工具函数。
Figma 的角度表示比较别扭。
特征为:基准角度朝上,对应向量为 (0, -1),角度方向为逆时针,角度范围限定为 (-180, 180]
,计算向量角度时要注意这个特征进行调整。
完整代码实现
线上 demo:
https://codepen.io/F-star/pen/WNPVWwQ?editors=0012。
代码实现:
运行一下,结果和属性面板一致。
结尾
Figma 只用宽高和变换矩阵来表达矩形,在数据层可以用精简的数据表达丰富的变形,此外在渲染的时候也能将矩阵运算交给 GPU 进行并行运算,是不错的做法。