前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图形编辑器开发:为什么我选择用 transform 矩阵表达图形的变形?

图形编辑器开发:为什么我选择用 transform 矩阵表达图形的变形?

作者头像
前端西瓜哥
发布2024-04-28 10:10:55
920
发布2024-04-28 10:10:55
举报

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

前段时间对自己的图形编辑器项目做了一次改造。

改用 transform 表达图形的变形,并废弃掉了原来的 rotation、x、y 属性。

然后再补上了图形的翻转的支持,以及斜切的支持。图形的变形操作算是补完了。

这里我简单说说这么做的原因。

我正在开发的 suika 图形设计工具: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/app/suika/

旋转、缩放和斜切

首先图形有基础的属性 x、y、width、height。

有些图形没有这 4 个属性,但其实也有,因为可以通过计算包围盒计算出来(比如贝塞尔曲线)。

然后我们要支持旋转,于是加了一个 rotation 属性(通常基于中心旋转。如果想随意指定,可以再补一个 pivot 属性指定旋转中心点)。

后来又要支持图形缩放。一般情况下,我们更改 width 和 height 就好了。

但有一种情况就不够用了,那就是 “翻转”,有两种情况:水平翻转和垂直翻转。

这时候我们就要引入缩放属性 scaleX 和 scaleY。

scaleX 如果是 1 表示不翻转,如果是 -1,表示水平翻转;scaleY 同理,不同的是它是垂直翻转。

如果都是 -1,那其实就是旋转了 180 度。

最后我们可能要 支持斜切 ,一般来说这种形变的情况是很少见的,甚至说有些编辑器极力避免这种情况的发生。

比如 Canva 图片编辑器会避免斜切的出现。如果同时缩放多个图形,图形只会改宽和高。

但如果一定要支持斜切(比如 Figma),我们只能上 transform 了。

虽说貌似可以补上一个 skewX 和 skewY 属性,但和 rotation 有一些冲突,后面会说为什么。

下面是 Figma 缩放多个图形的效果。

transform 矩阵

上面这些图形的变形属性,其实都可以用 transform 矩阵表示出来。或者叫模型矩阵。

变形矩阵用 6 个数值表示。

代码语言:javascript
复制
| a | c | tx|
| b | d | ty|
| 0 | 0 | 1 |

a 和 d 对应缩放值 scaleX、scaleY。

tx 和 ty 表示位移量,x 和 y 表示图形的位置。所以这里我把图形的 x 和 y 属性也丢掉了,默认为 (0, 0),放到 tx 和 ty 上了。

rotation 值如果对应旋转矩阵,可根据特性求。但 transfrom 不保证符合旋转矩阵的特征。

旋转矩阵其实是斜切中的特例。

所以还是不要太依赖旋转矩阵的特性。

计算 rotation,我们可以选择对一个基准方向的向量(比如 (1, 0)),应用 transform 得到新向量,作为这个图形的方向向量,计算出对应的 rotation。

代码语言:javascript
复制
const getTransformAngle = (tf, angleBase = { x: 1, y: 0 }) => {
  // 丢掉位移的影响,因为向量和点不同,位移后还是原来的向量
  tf = new Matrix(tf.a, tf.b, tf.c, tf.d, 0, 0);
  const angleVec = tf.apply(angleBase);
  return getSweepAngle(angleBase, angleVec);
};

最后是 skewX、skewY,对应是 c 和 b。基本没有什么用。

transform 有很多好处,首先它是底层属性,所有渲染引擎(比如 SVG、Canvas 2D)都支持用矩阵对图形表示形变。

其次也方便做多个形变的复合运算。

比如对一个已经形变的图形做中心旋转,只要给原来的变形矩阵左乘一个 “位移-旋转-位移” 的复合矩阵就可以了。

代码语言:javascript
复制
const dRotate = (dRotation, originTf, center) => {
  const rotateMatrix = new Matrix()
    .translate(-center.x, -center.y)
    .rotate(dRotation)
    .translate(center.x, center.y);

 // 记得要 “左乘” 新的矩阵
  return rotateMatrix.append(originTf);
}

这个思路的方向,要比带着一堆 rotation、scaleX 乱七八糟的属性基于几何算法写出一套复杂的逻辑简单多了。当然前提是你得理解矩阵到底在干什么,这个是基础,建议你花时间弄懂。

最后

选择 transform 矩阵的一些优点:

  1. 它是更底层的表达,能够非常精炼地表达一个图形的形变(虽然一眼看过去不是很直观);
  2. 同时基于矩阵运算,也很方便计算二次形变结果,左乘一个新的变形矩阵即可;
  3. 更容易兼容其他的用了 transform 风格的图形数据,比如 SVG;
本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-22,如有侵权请联系?cloudcommunity@tencent.com 删除

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

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

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 旋转、缩放和斜切
  • transform 矩阵
  • 最后
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com