2

I've been having an enormous amount of difficulty getting a set of rectangles to face a certain point on a canvas block. I'm iterating through a set of points, and drawing rectangles, which are supposed to all face a certain point.

First I set up the Radius, Focus point and Rectangle

var Angle = Math.PI;

_.each(Points, function(Point) {
var Radius = 10;

var Focus = {
    X: 500,
    Y: 1000
}

var Rect = [
{
    X: (Point.X - Radius/2),
    Y: (Point.Y - Radius/2)
},
{
    X: (Point.X + Radius/2),
    Y: (Point.Y - Radius/2)
},
{
    X: (Point.X + Radius/2),
    Y: (Point.Y + Radius/2)
},
{
    X: (Point.X - Radius/2),
    Y: (Point.Y + Radius/2)
}
];

Then, using underscore, I iterate through and used the method I read about on another response.

var index = 0;
_.each(Rect, function (V) {
    var dx2 = Focus.X - V.X;
    var dy2 = Focus.Y - V.Y;
    var dx2_ = dx2 * Math.cos(Angle) - dy2 * Math.sin(Angle);
    var dy2_ = dy2 * Math.sin(Angle) + dy2 * Math.cos(Angle);

    V.X = dx2_ + V.X;
    V.Y = dy2_ + V.Y; 

    Rect[index] = V;
    index++;
});

Then its all set up in the normal canvas stuff. The context and the fillStyle are defined beforehand.

ctx.beginPath();
ctx.moveTo(Rect[0].X, Rect[0].Y);
ctx.lineTo(Rect[1].X, Rect[1].Y);
ctx.lineTo(Rect[2].X, Rect[2].Y);
ctx.lineTo(Rect[3].X, Rect[3].Y);
ctx.lineTo(Rect[0].X, Rect[0].Y);

ctx.fill();

});

These are the initial squares (without the rotation each loop)

Without rotation Without Rotation

This is what I get instead (seems like the rectangles are being rotated around the point instead of rotating towards the point)

With angle set to pi With angle set to pi

The behavior that I'm trying to get is to have them facing towards the bottom middle. (500,1000) if the canvas is 1000x1000.

JSFiddle: http://jsfiddle.net/nmartin413/cMwTn/7/

I can't for the life of me figure out whats going wrong. If there's anything that stands out to you, please let me know :). Sorry for the long question, but this has really frustrated me.

Thanks in advance!

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
nmartin413
  • 60
  • 10
  • 2
    What happens instead of what you expect? – Alex Wayne Nov 29 '12 at 03:45
  • Sorry - forgot to mention that. I added some before and after images – nmartin413 Nov 29 '12 at 04:17
  • 1
    Why not use fillRect to draw a filled rectangle?? http://developer.mozilla.org/en-US/docs/Canvas_tutorial/Drawing_shapes – loxxy Nov 29 '12 at 04:21
  • That was where I started, but there's no way to rotate a rectangle made with fillRect. You can rotate the entire canvas, but not the rectangles themselves. Unless I'm mistaken... – nmartin413 Nov 29 '12 at 04:23
  • 1
    may be you like css3 solution ? [how-to-rotate-the-background-image-in-the-container](http://stackoverflow.com/questions/5087420/how-to-rotate-the-background-image-in-the-container) – zb' Nov 29 '12 at 04:31
  • I also considered this, but I cannot target individual canvas rectangles with css, as they've got no dom representation. I thought about just using div's, but with up to 1000 rectangles, I fear the performance hit – nmartin413 Nov 29 '12 at 04:33
  • ok, can you make jsbin/jsfiddle ? – zb' Nov 29 '12 at 04:35
  • Sure - here it is. Thanks for looking into this :) http://jsfiddle.net/nmartin413/cMwTn/7/ – nmartin413 Nov 29 '12 at 04:55

1 Answers1

1

Try not to draw the rectangles yourself, use ctx.rotate(angle); and ctx.fillRect(-Radius/2, -Radius/2, width, height); as it is more simple, and code-wise - much easier to read and manage. To accomplish this rotation, save and redraw the canvas every time you apply a transformation to a rectangle, using ctx.save(); and ctx.restore();

JS:

$(document).ready(function() {
    var Canvas = $('canvas')[0];
    var Focus = {
        X: 500,
        Y: 1000
    };
    var f = Focus;
    var angle = 0;
    var Radius = 10;
    _.each(Points, function($Point) {
        var ctx = Canvas.getContext('2d');
        var x = $Point.X;
        var y = $Point.Y;
        var width = Radius;
        var height = Radius;
        var cx = x - 0.5 * width;
        var cy = y - 0.5 * height;
        ctx.save();
        ctx.translate(x,y);
        var angle = (Math.atan2(f.Y-y,f.X-x));
        ctx.rotate(angle);
        ctx.fillStyle = "#ED1B24";
    ctx.fillRect(-Radius/2, -Radius/2, width, height);
        ctx.restore();
    });
});

JSFiddle: http://jsfiddle.net/mJNas/

extramaster
  • 2,635
  • 2
  • 23
  • 28