I need transform view from origin(250, 250) to origin(352, 315), and width/height change from (100.0, 100.0) to (68, 68). I know I can combine several CGAffineTransform function together, such as scale, rotate, translate. But i don't know how to count the order of those transformations, and the exact parameter of them. I have try several time, but can't move the view to correct position.
Anyone can help?
The CGAffineTransform type provides functions for creating, concatenating, and applying affine transformations. Affine transforms are represented by a 3 by 3 matrix: Because the third column is always (0,0,1) , the CGAffineTransform data structure contains values for only the first two columns.
We can also use CGAffineTransform to rotate views, using its rotationAngle initializer. This accepts one parameter, which is the amount in radians you want to rotate. There are three catches to using this function: You need to provide the value in radians specified as a CGFloat .
To change a UIView's position, a translate matrix is applied to the transform matrix. This will change the values tx and ty values of the transform matrix. This function creates an affine transform matrix translating the current transform with the provided values.
A little understanding about what is happening behind the scenes is always nice in these matrix transformations.
Apple docs has a great documentation about transforms, so let's use it.
A translation matrix looks like :
| 1 0 0 |
| 0 1 0 |
| tx ty 1 |
where (tx, ty)
is your translation vector.
A scaling matrix looks like :
| sx 0 0 |
| 0 sy 0 |
| 0 0 1 |
where sx
and sy
are the scale factor in the X and Y axis.
You want to concatenate these matrix using CGAffineTransformConcat
, but as according to its doc :
Note that matrix operations are not commutative—the order in which you concatenate matrices is important. That is, the result of multiplying matrix t1 by matrix t2 does not necessarily equal the result of multiplying matrix t2 by matrix t1.
You have to translate your view before scaling it, otherwise your translation vector will be scaled according to sx
and sy
coefficients.
Let's show it easily :
let scaleMatrix = CGAffineTransformMakeScale(0.68, 0.68)
let translateMatrix = CGAffineTransformMakeTranslation(102, 65)
let translateThenScaleMatrix = CGAffineTransformConcat(scaleMatrix, translateMatrix)
NSLog("translateThenScaleMatrix : \(translateThenScaleMatrix)")
// outputs : CGAffineTransform(a: 0.68, b: 0.0, c: 0.0, d: 0.68, tx: 102.0, ty: 65.0)
// the translation is the same
let scaleThenTranslateMatrix = CGAffineTransformConcat(translateMatrix, scaleMatrix)
NSLog("scaleThenTranslateMatrix : \(scaleThenTranslateMatrix)")
// outputs : CGAffineTransform(a: 0.68, b: 0.0, c: 0.0, d: 0.68, tx: 69.36, ty: 44.2)
// the translation has been scaled too
And let's prove it mathematically. Please note that when you perform an operation A then an operation B, the related matrix is computed by doing matB*matA, the first operation is on the right. Since multiplication is not commutative for matrix, it's important.
// Translate then scaling :
| sx 0 0 | | 1 0 0 | | sx 0 0 |
| 0 sy 0 | . | 0 1 0 | = | 0 sy 0 |
| 0 0 1 | | tx ty 1 | | tx ty 1 |
// The resulting matrix has the same value for translation
// Scaling then translation :
| 1 0 0 | | sx 0 0 | | sx 0 0 |
| 0 1 0 | . | 0 sy 0 | = | 0 sy 0 |
| tx ty 1 | | 0 0 1 | | sx.tx sy.ty 1 |
// The translation values are affected by scaling coefficient
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With