图形编辑器开发:实现选中图形的水平翻转和垂直翻转

2024-07-12 16:28:57 浏览数 (2)

大家好,我是前端西瓜哥。

今天我们来实现一个比较少用到的功能:对选中图形做水平翻转和垂直翻转

翻转实现分成这么 3 步:

  1. 计算选中图形的中心位置,作为翻转的翻转中心;
  2. 得到翻转矩阵;
  3. 给所有的图形应用翻转矩阵。

选中图形的中心

选中图形如果是单个,我们 选择图形的 OBB (带朝向的包围盒)的中点位置作为翻转中心

以矩形为例,就是计算给矩形的 [width/ 2, height / 2] 应用变形矩阵后的位置。

代码语言:javascript复制
getCenter(): IPoint {
  const tf = new Matrix(...this.attrs.transform);
  return tf.apply({
    x: this.attrs.width / 2,
    y: this.attrs.height / 2,
  });
}

这里用 width / height / transform 表达矩形的位置、大小、旋转、翻转等物理信息。

选中图形如果是多个,就计算每个图形的 AABB 包围盒(包围图形的最小矩形),然后将它们合并成一个大包围盒,取这个大包围盒的中心作为翻转中心

代码语言:javascript复制
const mergedBox = mergeBoxes(graphicsArr.map((item) => item.getBbox()));
// 翻转中心
const flipCenter = {
  x: box.minX / 2   box.maxX / 2,
  y: box.minY / 2   box.maxY / 2,
};

得到翻转矩阵

我们以水平翻转切入。

假设我们 基于 y 轴做水平翻转,本质就是 将图形的点的 x 值取反

一个点原来在右边(x > 0),水平翻转一下,跑到右边去了(x < 0)。同理,一个点原来在左边,水平翻转一下,跑到左边去了。

也就是说,等价于 x 乘以 -1,其他保持不变。这个操作对应的矩阵是缩放矩阵 Scale(-1, 1)

回到我们的对选中图形水平翻转。我们不是基于 y 轴做翻转,是对选中图形的中心做翻转。

所以我们需要先把图形移动到原点 Translate(-cx, -cy),然后再做翻转 Scale(-1, 1),最后再移动回来 Translate(cx, cy)

记住在原矩阵应用新的矩阵是要左乘的,不是右乘。图形需要应用的矩阵是:

代码语言:javascript复制
Translate(cx, cy) * Scale(-1, 1) * Translate(-cx, -cy)

用 pixi.js 的 Matrix 类的话,就是这样写。

代码语言:javascript复制
const flipMatrix = new Matrix()
  .translate(-flipCenter.x, -flipCenter.y) // 先左乘 “移动到原点” 的矩阵
  .scale(-1, 1) // 再缩放
  .translate(flipCenter.x, flipCenter.y); // 最后移动回来

也可以使用其他矩阵库,用法类似。

应用矩阵

最后给选中的每个图形 应用这个翻转矩阵(记住是左乘这个矩阵)。

代码语言:javascript复制
for (const graphics of graphicsArr) {
  graphics.attrs.transform = flipMatrix.append(graphics.attrs.transform);
}

至此,翻转就完成了。

就是如此简单。

拓展延伸

虽然这里只是讲如何翻转,但我想优秀的读者可能已经察觉到了,开始举一反三了。

这次做的是翻转需求,如果下次需求是要做个旋转,其实也是一个道理,将中间的缩放矩阵换成缩放矩阵就行了。

或者更复杂一些,基于某条线做镜像对称,其实也就是在原来缩放的基础上再补上一个旋转。

这就是引入矩阵这一数学工具的含金量。

你说我不用矩阵,用解析几何的做法也能解。的确可以,但这种方式难度高也容易写错,写久了自己回过头来发现自己也看不懂了,也实属正常,没有可持续性。

以前我是用几何算法去实现的,那可太痛苦了,纸上画来画去,推导一番好像想通了,翻译成代码,发现效果不对,再做调试,最后还是要重新看推导过程是不是哪来不对,反复几遍才做完。

当然,使用矩阵实现需求是有个前提的,就是图形要用矩阵来表达。

或者可以不用矩阵表达,但是可以转换成矩阵的表示,且能在做完矩阵变换后转换回来。

但通常来说非矩阵表达转换为矩阵,转换结果只是矩阵的子集,也就是说有些矩阵是无法转换回原表达,会丢失一些信息,这点要注意

此外就是对矩阵有一点点认识,不然不会用,看着干瞪眼,不过网上很多资料,对读者来说应该问题不大。

结尾

我是前端西瓜哥,欢迎关注我,学习更多图形编辑器知识。

0 人点赞