Erwin KIRICHNER
Erwin KIRICHNER

Reputation: 47

Drawing an image inside a circle using canvas

I have been trying to center an image inside a canvas drawn circle, the circle is centered in the middle of the page but the image that I want to draw inside it can't.

const background = await Canvas.loadImage(`./backgrounds/${UserJSON[message.author.id].background}.png`);
        const canvas = Canvas.createCanvas(250, 400);
        const context = canvas.getContext('2d');
        context.drawImage(background, 0, 0, canvas.width, canvas.height);


        context.strokeStyle = '#0099ff';
        context.strokeRect(0, 0, canvas.width, canvas.height);

        context.font = '28px sans-serif';
        context.fillStyle = '#ffffff';
        context.fillText(`${message.author.username}`, canvas.width / 4, canvas.height / 1.6);

        context.beginPath();
        context.arc(canvas.width / 2, canvas.height / 2, 70, 0, Math.PI * 2, true);
        context.closePath();
        context.clip();

        const avatar = await Canvas.loadImage(message.author.displayAvatarURL({ format: 'jpg', size: 4096 }));
        context.drawImage(avatar, 0, 0, 250, 320);


        const attachment = new MessageAttachment(canvas.toBuffer(), 'profile-image.png');

I don't know what I'm doing wrong at "drawImage", I can't seem to minimize the image to fit the circle or anything else. Below I put my discord avatar and the way it's drawn on the canvas

enter image description here enter image description here

Upvotes: 0

Views: 1868

Answers (1)

Newbie
Newbie

Reputation: 4819

You need to make some calculations on your own. drawImage will take a bitmap and project it on whatever rectangle you gave it (will not preserve aspect ratio). So you need to make all the center and cover calculations.

const canvas = Canvas.createCanvas(250, 400);
const context = canvas.getContext('2d');
context.fillStyle = '#6f6f6f';
context.fillRect(0, 0, canvas.width, canvas.height);

const circle = {
    x: canvas.width / 2,
    y: canvas.height / 2,
    radius: 70,
}

context.beginPath();
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2, true);
context.closePath();
context.clip();

const avatar = await Canvas.loadImage('./image.jpg');
console.log(avatar.height, avatar.width);

// Compute aspectration
const aspect = avatar.height / avatar.width;
// Math.max is ued to have cover effect use Math.min for contain
const hsx = circle.radius * Math.max(1.0 / aspect, 1.0);
const hsy = circle.radius * Math.max(aspect, 1.0);
// x - hsl and y - hsy centers the image
context.drawImage(avatar,circle.x - hsx,circle.y - hsy,hsx * 2,hsy * 2);

enter image description here enter image description here

Upvotes: 4

Related Questions