So I know there are threads about it already here, like that one. I followed the idea that was proposed in the thread above, and it works. However, I don't understand WHY it works.
Here is an example:
Let's say that i have a square centered at (100, 100), and its width/height is 100. So its top-left corner will be at (50, 50).
Now let's say that i want to zoom X2 into the square's center, that is, to zoom into (100, 100). So i will write the following transformation sequence:
translate(100, 100);
scale(2, 2);
translate(-100, -100);
So because the canvas apply the transformation in reverse order, my transformed square's top-left corner will be now at (0, 0), and its height/width will be 200.
Ok, let's say that now i want to zoom X2 into the right-bottom corner of the already transformed square. So intuitively, i would like to perform the following transformation sequence:
translate(200, 200);
scale(2, 2);
translate(-200, -200);
But it wont work, because again, the canvas apply transfomations in reverse order. That is to say, that if i sum up my two transformation sequences, i'll get:
// First Sequence
translate(100, 100);
scale(2, 2);
translate(-100, -100);
// Second Sequence
translate(200, 200);
scale(2, 2);
translate(-200, -200);
This means that the second sequence will be applied to each point before the first sequence (because the canvas will apply the transformation from bottom to top), and this is wrong. So as the thread in the link above suggest the following:
Because sequence 2 will be applied first, i should transform the point (200, 200) to its original coordinates, by applying to it the inverse of the first sequence. that is to say, if T1
is the matrix that represents the first sequence, then it will look like that:
// First Sequence
translate(100, 100);
scale(2, 2);
translate(-100, -100);
// Second Sequence
var point = SVGPoint(200, 200);
var transformedPoint = point.matrixTransform(T1.inverse());
translate(-transformedPoint.x, -transformedPoint.y);
scale(2, 2);
translate(transformedPoint.x, transformedPoint.y);
But why it works? I really don't understand why it should work like that... can anyone elaborate about it?
Thanks!