I have created pulse animation using html canvas. There is two rectangles. Rectangle’s positions is updated dynamically. The smaller rectangle has pulse animation. I have problem calculate it’s center position value.
Without scaling I get correct position. But when scaling position is incorrect. How to calculate scaled X and Y?
const canvas = document.createElement("canvas");
canvas.setAttribute("width", "500px");
canvas.setAttribute("height", "500px");
const ctx = canvas.getContext("2d");
const wrapper = document.getElementsByClassName("wrap")[0];
wrapper.appendChild(canvas);
let scale = 1;
let angle = 0;
const blockSize = 45; // Rectangle size
const pos = {x: 2, y: 1}; // Rectangle position
function anim(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
draw(ctx, pos)
update();
requestAnimationFrame(anim);
}
anim();
function draw(ctx, position){
ctx.fillStyle = "#000";
ctx.fillRect((position.x * blockSize - blockSize), (position.y * blockSize - blockSize), blockSize, blockSize);
// Smaller rectangle with pulse
ctx.fillStyle = "red";
const centerX = (position.x * blockSize - blockSize) / 2;
const centerY = (position.y * blockSize - blockSize) / 2;
const scaledX = centerX - (centerX * scale);
const scaledY = centerY - (centerY * scale);
ctx.setTransform(scale, 0, 0, scale, centerX, scaledY);
const recSize = 30;
const x = (position.x * blockSize - blockSize) + ((blockSize - recSize) / 2);
const y = (position.y * blockSize - blockSize) + ((blockSize - recSize) / 2);
ctx.fillRect(x, y, recSize, recSize);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
function update(){
angle += Math.PI / 140;
scale = 0.5 + Math.abs(Math.cos(angle));
}
<div class="wrap">
</div>
2
Answers
codepen
Here’s what this code does:
It draws the larger black rectangle as before.
It calculates the center of the larger rectangle.
It saves the current context state.
It applies the scaling transformation:
First, it translates to the center of the larger rectangle.
Then it applies the scaling.
Finally, it translates back.
It draws the smaller red rectangle.
It restores the context state.
Draw relative to origin
Scale objects from their local origin.
A box 20 by 20 pxs has 4 corners that are relative to a point
{x: 0, y: 0}
The top left corner is at
{x: -10, y: -10}
The bottom right corner is at
{x: 10, y: 10}
You can then draw the box by setting where its center point will be on the canvas.
Scaling or changing the size of the box moves all the points towards or away from the center point.
This can greatly reduce the complexity of the source code (as you can see in the example below).
Example
Example below rewrites from ground up.
fillSquare
draws a square centered on a point.Note The example uses the time as given by the
requestAnimationFrame
callbacks’ argument to control the rate of the animation, one pulse per second.