2

On html5 canvas I am drawing objects (rectangle, circle, etc...), these objects have transformation properties like scale, skew, rotation etc... These objects can be nested.

Problem occurs when I after applying transformations, I want to find exact x, y coordinate of given object, but its going over my head.

To all experts who is into interactive computer graphics; please help me solve this problem.

Thanks in advance.

DaBler
  • 2,695
  • 2
  • 26
  • 46
Software Enthusiastic
  • 25,147
  • 16
  • 58
  • 68
  • Duplicate: http://stackoverflow.com/questions/3630594/html5-canvas-transformation-matrix – Markus Jarderot Jun 05 '12 at 06:10
  • No this is not duplicate, it is similar to this question (http://stackoverflow.com/questions/8844525/get-position-on-canvas-after-rotating-translating-and-restoring) but not same . I am looking for similar answer for my queries. But thanks your reference link also helped... – Software Enthusiastic Jun 05 '12 at 09:27

2 Answers2

10

All affine transformations in 2D can be expressed as a matrix of the form:

    [ a  c  dx ]
T = [ b  d  dy ]
    [ 0  0   1 ]

This could be expressed with the method context.transform(a, b, c, d, dx, dy);.

When applied to some coordinate, (x,y), you first have to add a third coordinate, which is always 1: <x, y, 1>. Then you can multiply the transformation matrix to get the result:

[ a*x + c*y + dx ]
[ b*x + d*y + dy ]
[       1        ]

If you get anything other than '1' in the last coordinate, you have to divide the vector by it.


To go the other way, you have to invert the matrix:

[ d/M  -c/M  (c*dy - d*dx)/M ]
[ b/M   a/M  (b*dx - a*dy)/M ]
[  0     0          1        ]

where M is (a*d - b*c).


Multiple transformations could be applied in sequence, by multiplying their matrices. The order of the multiplications are important.


context.translate(dx,dy) <==> context.transform( 1,  0,  0,  1, dx, dy)
context.rotate(θ)        <==> context.transform( c,  s, -s,  c,  0,  0)
context.scale(sx,sy)     <==> context.transform(sx,  0,  0, sy,  0,  0)

where c = Math.cos(θ) and s = Math.sin(θ)


If you got some coordinate (x,y) in object-space, and you want to know where it will end up on the screen, you apply the transformation to it.

If you got some coordinate (x,y) on the screen, and you want to know which point on the object that is, you multiply by the inverse of the transformation.

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • this is somewhat confusing layout of the matrix elements, as setTransform(a,b,c,d,e,f) in the canvas API is laid out: [a, c, e \n b, d, f \n 0 0 1], see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform – Tom Larkworthy Nov 05 '15 at 00:38
  • @TomLarkworthy Thanks. Fixed. – Markus Jarderot Nov 05 '15 at 06:29
  • What method are you using to get the original coordinate? I am using ```var rect = canvas.getBoundingClientRect();``` ```var xcoord = (event.clientX - rect.left) * canvas.widht /rect.widht)``` ```return newX = xcoord *a + ycoord*c + e``` but that gives the wrong newX. – NicoWheat Dec 09 '19 at 16:05
0

Tom Larkworthy's answer is perfect, but with a minor typo. Correct formula to invert the matrix is:

[  d/M  -c/M  (c*dy - d*dx)/M ]
[ -b/M   a/M  (b*dx - a*dy)/M ]
[   0     0          1        ]
bruno
  • 26
  • 1