You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CGAffineTransform:矩阵连接与相互应用差异及矩阵相等性示例疑问

嘿,这个问题问到点子上了——CGAffineTransform的矩阵组合一直是iOS开发者容易踩的坑,尤其是变换顺序的问题,我来给你拆解清楚~

一、矩阵连接与“应用一个矩阵到另一个”的区别

其实本质上这俩说的是一回事,核心坑点在于变换顺序不满足交换律——先做A变换再做B,和先做B再做A,结果天差地别,而很多人会把直觉上的顺序和代码里的矩阵连接顺序搞混。

举个最直观的例子:假设你有两个变换:

  • tTranslate:向右平移100pt
  • tScale:横向纵向都放大2倍

如果我们用tTranslate.concatenating(tScale),得到的变换是先平移100pt,再放大2倍——原本在(50,50)的点会变成( (50+100)2, 502 ) = (300, 100)。

但如果反过来用tScale.concatenating(tTranslate),得到的是先放大2倍,再平移100pt——同样的点会变成(502+100, 502) = (200, 100),结果完全不同。

所以所谓“连接两个矩阵”就是用concatenating(_:)或者CGAffineTransformConcat(_:_:)做矩阵乘法,而“将一个矩阵应用于另一个”其实就是选择把哪个变换放在前面执行——你说“把缩放应用到平移上”,如果是指“平移之后再缩放”,那就是translate.concat(scale);如果是“缩放之后再平移”,那就是scale.concat(translate)。核心区别全在执行顺序上,矩阵乘法不交换,顺序错了结果就错了。

二、为什么第一个矩阵和第三个相等,而非第二个?

虽然你没贴具体示例,但根据这个问题的常见场景,大概率是涉及旋转变换和平移变换的组合——这里有个很关键的矩阵等式:

先执行旋转变换R,再执行平移变换T(v),等价于先执行“旋转后的平移”T(R*v),再执行旋转变换R

用代码说就是:

let rotation = CGAffineTransform(rotationAngle: .pi/2)
let translate = CGAffineTransform(translationX: 100, y: 0)
// 第一个矩阵:先旋转,再平移100pt
let matrix1 = rotation.concatenating(translate)

// 第三个矩阵:先平移“旋转后的100pt向量”,再旋转
// 旋转90度后,(100,0)会变成(0,100)
let translatedAfterRotation = CGAffineTransform(translationX: 0, y: 100)
let matrix3 = translatedAfterRotation.concatenating(rotation)

// matrix1 和 matrix3 是完全相等的!

而第二个矩阵应该是translate.concatenating(rotation)——也就是先平移100pt,再旋转90度,这和matrix1的执行顺序完全相反,结果自然不一样。

背后的数学逻辑是:旋转变换会改变平移向量的方向,所以“先旋转再平移”,等于把平移向量先做一次旋转,再用这个新的向量平移,最后旋转。这俩操作的矩阵乘积是完全相同的,所以matrix1和matrix3相等;而先平移再旋转,平移的是原始方向的向量,旋转后位置完全不同,所以和前两个都不一样。

内容的提问来源于stack exchange,提问作者Dannie P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:07:27