Baijs
Baijs

Reputation: 1847

Rotate a rectangle around a certain point in canvas

Im trying to rotate a rectangle around the center of its parent rectangle. The child's distance to its parents borders must always stay the same. I almost succeeded but there seems to be a small error in my approach. I just can't seem to find the problem.

Example :

http://jsfiddle.net/FJ789/3/

I'm using the following formule to rotate around the pivot point.

var rotateAroundPoint = function(point, pivotPoint, sin, cos)
{
    position =
    {
        x : cos * (point.x - pivotPoint.x) - sin * (point.y - pivotPoint.y) + pivotPoint.x
    ,   y : sin * (point.x - pivotPoint.x) + cos * (point.y - pivotPoint.y) + pivotPoint.y
    };

    return position;
}

Upvotes: 0

Views: 1872

Answers (2)

Nasser
Nasser

Reputation: 13131

enter image description here

Manipulate[
 Module[{opt}, opt = {SphericalRegion -> True, Axes -> False, Boxed -> False, 
    ViewVertical -> {0, 0, 1}, ViewPoint -> {.8, 1, .7}, 
    PlotRange -> {{-4, 4}, {-4.5, 4.5 }, {-1.5, 1.5}}, ImageSize -> 200, ImageMargins -> 1};

  theta = Mod[theta + .1, 2 Pi]; t;
  Grid[{
    {Graphics3D[{Rotate[{Cuboid[{3, -3, 0}, {-3, 3, .2}], 
         Rotate[{{Gray, Cuboid[{.5, -.5, .2}, {-.5, .5, .25}]}}, 
          2 theta, {0, 0, 1}, {0, 0, 1}]}, .5 theta, {0, 0, 1}, {0, 0,1}]}, opt],
     Graphics3D[{Rotate[{Cuboid[{3, -3, 0}, {-3, 3, .2}], 
        {Gray,Cuboid[{2.5, -2.5, .2}, {2, -2, .35}]}},2 theta,{0, 0, 1},{0, 0, 1}]},opt]},
    {Graphics3D[{Rotate[{Cuboid[{3, -3, 0}, {-3, 3, .2}], 
         Rotate[{Cuboid[{1.5, -1.5, .2}, {-1.5, 1.5, .35}], 
           Rotate[{Gray, Cuboid[{.75, -.75, .35}, {-.75, .75, .55}]},3 theta, 
           {0, 0, 1}, {0, 0, 1}]}, 
          2 theta, {0, 0, 1}, {0, 0, 1}]}, .5 theta, {0, 0, 1}, {0, 0,1}]}, opt],
     Graphics3D[{Rotate[{Cuboid[{3, -3, 0}, {-3, 3, .2}], 
         Rotate[{Cuboid[{1.5, -1.5, .2}, {-1.5, 1.5, .35}], 
           Rotate[{{Gray, Cuboid[{.75, -.75, .35}, {-.75, .75, .55}]},
              Rotate[{{Red,Cuboid[{.45, -.45, .55}, {-.45, .45, .75}]}},4 theta, 
             {0, 0, 1}, {0, 0, 1}]}, 
            3 theta, {0, 0, 1}, {0, 0, 1}]}, 
          2 theta, {0, 0, 1}, {0, 0, 1}]}, .5 theta, {0, 0, 1}, {0, 0, 1}]}, opt]}}]],
 {{t, 0, "run"}, 0, 100, .01},
 {{theta, 0}, None},
 {{a, 0}, None},
 TrackedSymbols :> {t}
 ]

Upvotes: 1

markE
markE

Reputation: 105015

You don't have to calc bounding boxes when transforming (translating and rotating) because those transforms will actually rotate the entire canvas (not just the newly drawn elements)

This means you can transform the canvas and then draw new elements normally.

For example, this code will draw parent and child in their same positions relative to each other even after context.translate and context.rotate:

ctx.fillRect(0,0,100,50);   // parent
ctx.fillRect(10,10,30,20);  // child

Demo: http://jsfiddle.net/m1erickson/WQ4tU/

In each animation frame:

  • Clear the canvas
  • Save the context state
  • Translate to the rotation centerpoint
  • Rotate the canvas
  • Draw the parent-child rects (allow for previous contect.translate by offsetting their x/y by half their width/height)
  • Restore the context to its original state (untranslated and unrotated)

Here's code:

ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();

// translate to the rotation centerpoint

ctx.translate(150,150);

// rotate

ctx.rotate(radianAngle);

// draw parent rect
// allow for previous ctx.translate by offsetting x/y by half width/height

ctx.fillStyle="green";
ctx.fillRect(-50,-30,100,60);

// draw child rect
// allow for previous ctx.translate by offsetting x/y by half width/height

ctx.fillStyle="red";
ctx.fillRect(-45,-25,30,20);

// restore the original context state

ctx.restore();

Upvotes: 1

Related Questions