DOMMatrix 矩阵的具体应用: 坐标变换, 让你从繁杂的数学运算中解放出来!

矩阵

在计算机中图形的世界里, 我们往往使用矩阵来表达变换. 这些变换包括 平移 (Translation) 旋转 (Rotation) 缩放 (Scaling) 剪切 (Shear) 和 反射 (Reflection)

对于二维世界中的变换, 我们往往使用 3 × 3 的矩阵表示上述变换. 上面的变换统称为仿射变换. 下面是一个二维变换中的放射变换矩阵

线性变换和仿射变换 对于二维世界而言, 线性变换矩阵是一个 2 × 2 矩阵, 这个变换矩阵可以做到 Rotation Scaling Shearing, 再加一个 Reflection(反射)

放射变换多一个阶是为了表达平移, 𝑎、 𝑏、 𝑐、 𝑑 定义了线性变换部分,而 𝑡𝑥 和 𝑡𝑦 定义了平移部分

很自然想到的疑问是, 用 top left 和 scale 来表达变换有什么不好的地方呢? 用矩阵有什么特别的好处吗?

逆矩阵

使用矩阵, 最大的好处是可以很方便的表达逆变换. 使用逆变换, 可以很方便的做坐标系转换. 例如当📷相机相对屏幕移动了, 如何求出相机相对世界的坐标?

或者更加朴素一点, 画布上的内容是经过了一系列变换才开始绘制, 如何快速求出鼠标相对画布坐标系的位置?

DOMMatrix

canvas.getTransform() 得到的数据类型是 DOMMatrix 表示矩阵, 并且有两种表达形式, 一种是 𝑎、 𝑏、 𝑐、 𝑑、 𝑡𝑥、𝑡𝑦

另一种是一个4阶矩阵, 用 m11 ~ m44 表示, 这是为了统一 3D 和 2D 的放射变换, 所以用了四阶矩阵.

DOMMatrix 常见方法

构造一个 DOMMatrix

方法还蛮多的, 一种是 new DOMMatrix('matrix(1, 0, 0, 1, 0, 0)'); 不过 DOMMMatrix 还内置了很多静态方法用于创建一个新的矩阵, 例如 DOMMatrix.fromFloat32Array DOMMatrix.fromFloat64Array 以及 DOMMatrix.fromMatrix

还有一个不是创建新矩阵, 但是可以将当前矩阵通过一个参数变成你需要的矩阵, 有点类似 setTransform, matrix.setMatrixValue('matrix(1, 0, 0, 1, 30, 50)');

mutiply

用来表示两个矩阵的变换后的结果, 不过要注意顺序

js 复制代码
let matrix1 = new DOMMatrix().translate(50, 50);
let matrix2 = new DOMMatrix().rotate(45);
let resultMatrix = matrix1.multiply(matrix2);
// resultMatrix 先应用 matrix2 的旋转,再应用 matrix1 的平移

inverse & invertSelf

自然就是逆矩阵啦, invertSelf 就是将当前矩阵变成其逆矩阵

translate, translateSelf, scale, scaleSelf, rotate, rotateSelf

见名知义

transfromPoint

将一个点应用变换, 返回应用当前矩阵变换后的点坐标

Demo

前面提到了一个场景, 当一个画布中的内容绘制之前经历了一系列变换, 那么如何将鼠标位置转换为画布内容的坐标呢? (也就是将相对 canvas 坐标系的坐标转为画布内容坐标) 这里我们就需要通过 inverse 和 transfromPoint 两个方法

关键函数

js 复制代码
      const updateCursor = (e) => {
        const x = e.clientX - canvas.getBoundingClientRect().left;
        const y = e.clientY - canvas.getBoundingClientRect().top;
        const trans = ctx.getTransform();
        const inverse = trans.inverse();
        const pos = inverse.transformPoint({ x, y });
        cursorPos.x = pos.x;
        cursorPos.y = pos.y;
        drawCursor(pos);
      }
相关推荐
去伪存真10 小时前
并发量一高就装死?Agent 全链路“防猝死”手册
前端·agent
Moment10 小时前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
AiMan10 小时前
先确认能不能一次把Microsofat Copilot所有内容打包一个文件导出
前端
总要学点什么10 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技10 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥11 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易11 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭12 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter
严肃小白兔12 小时前
TanStack Router 更新构建工具链:Node.js 兼容性、路由分割与前端工程实践
前端·node.js·状态模式
IT_陈寒13 小时前
Vue这个奇葩的响应式问题让我加班到凌晨
前端·人工智能·后端