1

It may be seem like a hard question, I'm curious if we could find the exact x,y pixel position at point b after apply settransform and what is the formula?

var ctx = ctx1.getContext("2d");
ctx.setTransform(1,tan(-0.2),0,1,0,0);
ctx.beginPath();
ctx.moveTo(10,0); //point a
ctx.lineTo(200,0); //point b
ctx.stroke();
Proyb P
  • 35
  • 1
  • 1
  • 7

2 Answers2

2

To transform a point via the setTransform values.

Assuming setTransform(a,b,c,d,e,f) and a point x,y then the transformation is

var transformPoint = function(x,y,a,b,c,d,e,f){
    var p = {};
    p.x = x * a + y * c + e;
    p.y = x * b + y * d + f;
    return p;  // returns the transformed point.
}
var pointA = transformPoint(20,0,1,Math.tan(-0.2),0,1,0,0);
var pointB = transformPoint(200,0,1,Math.tan(-0.2),0,1,0,0);
Blindman67
  • 51,134
  • 11
  • 73
  • 136
0

Unfortunately, there is no simple way to actieve that. You have to know the current transformation matrix exactly to calculate mapped positions, but unfortunately, only Google has implemented CanvasRenderingContext2D.currentMatrix.

The only thing you can do is to keep track of the current transformation yourself. You can find some help in this StackOverflow question.

If you use this library, I recommend you to employ the former example:

var t = new Transform();
t.rotate(5);
var m = t.m;
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);

What is more, I would event wrap that, so you can use it like:

Transform.prototype.apply = function(ctx) {
    var m = this.m;
    ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
};

var t = new Transform();
t.rotate(5);
t.apply(ctx);

If you kept track of the transformation, you can get your coordinates:

var t = new Transform();
t.m = [1,tan(-0.2),0,1,0,0];
t.apply(ctx);
ctx.beginPath();
ctx.moveTo(10,0); //point a
ctx.lineTo(200,0); //point b
ctx.stroke();
var mapped = t.transformPoint(200, 0);
console.log(mapped[0], mapped[1]);
Community
  • 1
  • 1
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
  • When you use `setTransform` you do know the values as it replaces the current transform unlike `transform` – Blindman67 Dec 13 '15 at 14:09
  • That's right, but I feel like the next question would be "what about rotate?" – Tamas Hegedus Dec 13 '15 at 14:10
  • Easy to apply the rotate to the values. Start `ang + rotate` angle and calc the two vectors for `a,b,c,d` `d = a = Math.cos(ang)` and `c = -b = Math.sin(ang)` Infact it is easy to track the 2D transform rotations are additive, scale multiplies and translate adds. Using the setTransform directly is a lot easier once you are familiar with matrices. Using a lib will only obfuscate everything. – Blindman67 Dec 13 '15 at 14:19
  • That lib is 50 lines long, you can write it yourself if you wish. You cannot have inlined matrix multiplication allover your code, **that will obfuscate things**. Encapsulating logics is a good thing. Makes the code more readable. In fact, every graphics library has builtin matrix and vector types so you don't have to write them yourself. Your approach is certainly the best if you only have one setTransform, but if you have to *concatenate* a rotation, then it's better to have transformation class. – Tamas Hegedus Dec 13 '15 at 14:41
  • Using standard SVGMatrix or SVGTransform would be the best, but that's not widely supported. – Tamas Hegedus Dec 13 '15 at 14:42
  • I just feel that to many answer are just pointing to 3rd party libraries and do not address the question directly. You answer has not shown how to transform a point, it has just pointed to a library and given instructions on using it. – Blindman67 Dec 13 '15 at 15:21
  • Hmm, he explicitly asked for a formula, so I guess you're right in this case. But I will leave my answer here, because it's not wrong either. – Tamas Hegedus Dec 13 '15 at 15:45