Like button
This is a post where I explain how I animated my blog’s like button
I’m in the middle of a lot of experimenting and improving things with Astro, so I added a like button to my posts.
My idea is to copy the like button policy from Bear Blog, which I really like. Basically: you can like, but you can’t unlike. If you liked something by accident, sorry, there’s nothing you can do. No refunds.
I don’t want to get into the technical details of how the logic was implemented, but I do want to show how the visual part works.
I wanted some confetti to appear when someone clicked the like button, so I installed canvas-confetti, a very popular npm package. It works really well and is very configurable.
At first, I made the animation appear only the first time you clicked the button (when you didn’t have a like yet and then gave one). But that felt a little boring. I want people to be able to click it several times. One click = one reward.
Then I thought confetti didn’t really match the idea of a like. A heart felt much better. Luckily, the same package lets you replace the confetti with custom shapes, including emojis.
This is how I did it:
First, we import the package and create the heart shape. We also set the scalar we’re going to use later, because otherwise the emoji can look pixelated.
import confetti from 'canvas-confetti';
const heartShape = confetti.shapeFromText({
text: '❤️',
scalar: 3
});
Then we get the point where we want the hearts to come from. The default origin is the center 0,0, but we want them to come from the button’s position on the screen.
We also calculate the launch angle depending on which side of the screen the button is on.
const rect = button.getBoundingClientRect();
const origin = {
x: (rect.left + rect.width / 2) / window.innerWidth,
y: (rect.top + rect.height / 2) / window.innerHeight
};
const angle = origin.x < 0.5 ? 70 : 110;
And then we call confetti:
void confetti({
angle,
gravity: 0.55,
origin,
particleCount: 5,
scalar: 3,
shapes: [heartShape],
spread: 45,
startVelocity: 30,
ticks: 300
});
The parameters are pretty self explanatory, but if not, you can take a quick look at the documentation.
And this is how it turned out:
