I am trying to rotate a square about its center in javascript. Although in this case I am using canvas to draw the square, I need to have a functional method of rotating the square for use elsewhere so just rotating the canvas is not acceptable. This is what I have so far
var thecanvas = this.myCanvas;
var canvaswidth = thecanvas.width;
tlx = (0 - ((canvaswidth * 0.6) / 2));
tly = (0 - ((canvaswidth * 0.6) / 2));
trx = (0 + ((canvaswidth * 0.6) / 2));
tryy = (0 - ((canvaswidth * 0.6) / 2));
blx = (0 - ((canvaswidth * 0.6) / 2));
bly = (0 + ((canvaswidth * 0.6) / 2));
brx = (0 + ((canvaswidth * 0.6) / 2));
bry = (0 + ((canvaswidth * 0.6) / 2));
tlx = (((tlx) * (this._cosD(orientation))) - ((tly) * (this._sinD(orientation))));
tly = ((tlx) * (this._sinD(orientation)) + (tly) * (this._cosD(orientation)));
trx = (((trx) * (this._cosD(orientation))) - ((tryy) * (this._sinD(orientation))));
tryy = ((trx) * (this._sinD(orientation)) + (tryy) * (this._cosD(orientation)));
blx = ((blx) * (this._cosD(orientation)) - (bly) * (this._sinD(orientation)));
bly = ((blx) * (this._sinD(orientation)) + (bly) * (this._cosD(orientation)));
brx = ((brx) * (this._cosD(orientation)) - (bry) * (this._sinD(orientation)));
bry = ((brx) * (this._sinD(orientation)) + (bry) * (this._cosD(orientation)));
tlx = (tlx + (canvaswidth / 2));
tly = (tly + (canvaswidth / 2));
trx = (trx + (canvaswidth / 2));
tryy = (tryy + (canvaswidth / 2));
blx = (blx + (canvaswidth / 2));
bly = (bly + (canvaswidth / 2));
brx = (brx + (canvaswidth / 2));
bry = (bry + (canvaswidth / 2));
var c2 = thecanvas.getContext('2d');
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(tlx, tly);
c2.lineTo(trx, tryy);
c2.lineTo(brx, bry);
c2.lineTo(blx, bly);
c2.closePath();
c2.fill();`
orientation is a value from -90-90 in degrees. This code starts to rotate the square but the square continues to "squish" until it is completely gone by 90 degrees. Obviously my formula for rotation is thrown off somewhere but I cant figure out how.
You could manually implement a transformation matrix. This allows you to set up the matrix for both read and write, then apply it to the points returning absolute points with the new actual values without the need or hassle to make special code for each use-case.
The formula for the (2D affine) using a 3x3 matrix would be:
or simplified in JavaScript:
Now you would need to multiply the matrix with another to add rotation, translation, scale etc. The common way of doing this is this way - assume we have an object holding our values, you could do:
With the core set up you can now add methods to do for example rotation:
scale:
translate:
and so forth depending on your needs. Note that these will accumulate as with the ordinary canvas/SVG matrix. Reset to identity to remove all transforms.
All you need to do now is to feed your points after settings transformation to get the absolute points - lets say we have a box of 100x100 we want to rotate at center:
Adding this to the prototype:
will allow us to do:
Demo
Red box is original coordinates, blue is the transformed points which we now have access to:
If you don't want to implement this yourselves, or want a more extensive solution, feel free to check out my (free) matrix solution here.
The future will give us
currentTransform
on the context (currently only available in Chrome, Firefox struggles with a bug) returning aSVGMatrix
object which you can use in pretty much the same way as the above implementation.