Reputation: 17
I am trying to make various shapes have a pulse like effect in canvas and managed to do it with a circle,
function drawCircle() {
// color in the background
context.fillStyle = "#EEEEEE";
context.fillRect(0, 0, canvas.width, canvas.height);
// draw the circle
context.beginPath();
var radius = 25 + 20 * Math.abs(Math.cos(angle)); //radius of circle
context.arc(25, 25, radius, 0, Math.PI * 2, false); //position on canvas
context.closePath();
// color in the circle
context.fillStyle = "#006699";
context.fill();
//'pulse'
angle += Math.PI / 220;
requestAnimationFrame(drawCircle);
}
drawCircle();
but I'm not sure how to go about doing any other shape. What I have so far for my triangle is
function drawTriangle() {
// draw the triangle
context.beginPath();
context.moveTo(75, 50);
context.lineTo(100, 75);
context.lineTo(100, 25);
context.fill();
context.rect(215, 100, Math.PI * 2, false); //position on canvas
context.closePath();
// color in the triangle
context.fillStyle = "#3f007f";
context.fill();
//'pulse'
angle += Math.PI / 280;
requestAnimationFrame(drawTriangle);
}
drawTriangle();
Any insight would be appreciated.
Upvotes: 1
Views: 2849
Reputation: 136776
This can be simply achieved by changing the scale of the context matrix.
All you need to find is the position of the scaling anchor of your shape so that you can translate the matrix to the correct position after the scale has been applied.
In following example, I'll use the center of the shape as scaling anchor, since it seems it is what you wanted.
The extended version of the matrix transformations would be
ctx.translate(anchorX, anchorY);
ctx.scale(scaleFactor, scaleFactor);
ctx.translate(-anchorX, -anchorY);
which in below example has been reduced to
ctx.setTransform(
scale, 0, 0,
scale, anchorX - (anchorX * scale), anchorY - (anchorY * scale)
);
var ctx = canvas.getContext('2d');
var angle = 0;
var scale = 1;
var img = new Image();
img.src = 'https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png';
anim();
function anim() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateScale();
drawCircle();
drawTriangle();
drawImage();
ctx.setTransform(1, 0, 0, 1, 0, 0);
requestAnimationFrame(anim);
}
function updateScale() {
angle += Math.PI / 220;
scale = 0.5 + Math.abs(Math.cos(angle));
}
function drawCircle() {
ctx.beginPath();
var cx = 75,
cy = 50,
radius = 25;
// for the circle, centerX and centerY are given
var anchorX = cx,
anchorY = cy;
// with these anchorX, anchorY and scale,
// we can determine where we need to translate our context once scaled
var scaledX = anchorX - (anchorX * scale),
scaledY = anchorY - (anchorY * scale);
// then we apply the matrix in one go
ctx.setTransform(scale, 0, 0, scale, scaledX, scaledY);
// and we draw normally
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.fill();
}
function drawTriangle() {
ctx.beginPath();
// for the triangle, we need to find the position between minX and maxX,
// and between minY and maxY
var anchorX = 175 + (200 - 175) / 2,
anchorY = 25 + (75 - 25) / 2;
var scaledX = anchorX - (anchorX * scale),
scaledY = anchorY - (anchorY * scale);
ctx.setTransform(scale, 0, 0, scale, scaledX, scaledY);
ctx.moveTo(175, 50);
ctx.lineTo(200, 75);
ctx.lineTo(200, 25);
ctx.fill();
}
function drawImage() {
if (!img.naturalWidth) return;
// for rects, it's just pos + (length / 2)
var anchorX = 250 + img.naturalWidth / 2,
anchorY = 25 + img.naturalHeight / 2;
var scaledX = anchorX - (anchorX * scale),
scaledY = anchorY - (anchorY * scale);
ctx.setTransform(scale, 0, 0, scale, scaledX, scaledY);
ctx.drawImage(img, 250, 25);
}
<canvas id="canvas" width="500"></canvas>
Upvotes: 1