Chris G-Jones
Chris G-Jones

Reputation: 626

Rotate a full size canvas image from a centerpoint without moving other canvas images

the example of the code below can be viewed here - http://dev.touch-akl.com/celebtrations/

What I have been trying to do is draw 2 images onto the canvas (glow and then flare. links for these images are below)

http://dev.touch-akl.com/celebtrations/wp-content/themes/beanstalk/img/flare.jpg

http://dev.touch-akl.com/celebtrations/wp-content/themes/beanstalk/img/blue-background.jpg

The goal is for the 'blue-background' image to sit on the canvas at the height and width of the container, and for the 'flare' image to be drawn ontop of this image with a blending mode and rotated with an animation to create a kind of twinkle effect.

My problem is that because the images I am using are rectangular when the 'flare' rotates at certain points you can see the edges of the layer underneath...

What I tried to do was find the diagonal width of the container using trigonometry and draw the 'flare' image at that width so that it always covered the whole canvas but alas you can still see the background layer at some points (but much less than before).

I need a way for the flare image to always cover the whole canvas, can anyone point me in the right direction please?

  var banner = $('#banner'),
    flare = document.getElementById('flare'),
    glow = document.getElementById('glow'),
    canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    blendMode = "multiply";

$window.load(function(){

    _canvasWidth = banner.outerWidth(),
    _canvasHeight = banner.outerHeight();

    canvas.width = _canvasWidth;
    canvas.height = _canvasHeight;

    var _flareSum = (_canvasWidth * _canvasWidth) + (_canvasHeight * _canvasHeight);
        _flareWidth = Math.sqrt(_flareSum); 

    _angle = 0;

    setInterval(function() {

        _angle = _angle +0.25;

        // draw the bg without a blend mode
        ctx.globalCompositeOperation = "source-over";  
        ctx.drawImage(glow, 0, 0, _canvasWidth, _canvasHeight); 
        ctx.save();

        // clear the canvas
        // ctx.clearRect(0, 0, _canvasWidth, _canvasHeight);

        ctx.translate( _canvasWidth/2, _canvasHeight);  // move to center point

        ctx.globalCompositeOperation = blendMode;
        ctx.rotate(Math.PI / 180 * (_angle)); // 1/2 a degree
        ctx.drawImage(flare, -_flareWidth/2, -_flareWidth/2, _flareWidth, _flareWidth); // redraw ia=mages

        ctx.restore();

        //console.log(_angle)

    }, 1);

Upvotes: 0

Views: 131

Answers (1)

markE
markE

Reputation: 105035

If I understand correctly, you need the shortest part of the flare to still cover the canvas when the flare is rotated at any angle.

Since you're only showing half the flare at any time, the shortest part of the flare is the distance from the flare center to the top of the flare:

enter image description here

var flareMinHeight = flare.height/2;

The longest length the flare must cover is from the flare rotation point to the top-left of the canvas.

enter image description here

var dx=rotationPointX;
var dy=rotationPointY;
var requiredLength=Math.sqrt(dx*dx+dy*dy);

So you will need to scale the flare to be at least the length computed above:

var minScale = requiredLength / flareMinHeight;

Upvotes: 1

Related Questions