前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图形编辑器开发:实现选中图形的水平翻转和垂直翻转

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

作者头像
前端西瓜哥
发布2024-07-12 16:28:57
740
发布2024-07-12 16:28:57
举报
文章被收录于专栏:前端西瓜哥的前端文章

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

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

翻转实现分成这么 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);
}

至此,翻转就完成了。

就是如此简单。

拓展延伸

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

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

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

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

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

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

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

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

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

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

结尾

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端西瓜哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 选中图形的中心
  • 得到翻转矩阵
  • 应用矩阵
  • 拓展延伸
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档