Javascript

Custom element hearts for valentine2 min read

Tomorrow is valentines day, so what could be more fitting than making a custom valentine-hearts element for your web page?

Coding might be for work, but sometimes it should just be for fun.

Lets create a custom element that can be added to a page like this:

<!DOCTYPE html>
<html lang=“en”>
<head>

<script type=“module” src=“/valentine-hearts.js”></script>
</head>
<body>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.

</p>
<valentine-hearts></valentine-hearts>
</body>
</html>

Time for some fun!

class ValentineHearts extends HTMLElement {
#shadowRoot;

constructor() {
super();
this.#createShadowRoot();
}

#createShadowRoot() {
this.#shadowRoot = this.attachShadow({ mode: ‘open’ });
this.#shadowRoot.innerHTML = `
<style>
:host {
–heart-size: 1em;
–heart-color: red;
–heart-speed: 30s;

pointer-events: none;
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10000;
overflow: hidden;
}

heart {
opacity: 0;
display: block;
width: var(–heart-size);
height: var(–heart-size);
position: absolute;
left: calc(var(–heart-x-offset) – 4%);
background: var(–heart-color);
transform: rotate(45deg) scale(0);
transition: top var(–heart-speed) linear,
opacity 1s ease-in-out,
transform 1s ease-in-out;
animation-duration: 6s;
animation-iteration-count: infinite;
will-change: top, left, opacity, transform;
}

heart::before {
content: ‘ ‘;
display: block;
width: var(–heart-size);
height: var(–heart-size);
border-radius: calc(var(–heart-size) / 2);
position: absolute;
top: 0;
left: calc(var(–heart-size) * -0.5);
background: var(–heart-color);
}

heart::after {
content: ‘ ‘;
display: block;
width: var(–heart-size);
height: var(–heart-size);
border-radius: calc(var(–heart-size) / 2);
position: absolute;
top: calc(var(–heart-size) * -0.5);
left: 0;
background: var(–heart-color);
}

@keyframes sway {
0% {
left: calc(var(–heart-x-offset) – 4%);
}

50% {
left: calc(var(–heart-x-offset) + 4%);
}

100% {
left: calc(var(–heart-x-offset) – 4%);
}
}
</style>
`;
}

connectedCallback() {
setInterval(() => this.#spawnHeart(), 2000);

for (let i = 0; i < 20; i++) {
this.#spawnHeart();
}

this.addEventListener(‘resize’, () => this.#resize());
this.#resize();
}

#resize() {
this.style.width = `${window.clientWidth}px`;
this.style.height = `${document.body.clientHeight}px`;
}

#spawnHeart() {
const heart = document.createElement(‘heart’);

heart.style.top = `${Math.round(Math.random() * 100)}%`;
heart.style.setProperty(‘–heart-x-offset’, `${Math.random() * 100}%`);

const brightness = Math.random();
heart.style.setProperty(
‘–heart-color’,
`rgb(255, ${Math.round(brightness * 150)}, ${Math.round(brightness * 50)})`
);

this.#shadowRoot.appendChild(heart);

setTimeout(() => {
heart.style.animationName = ‘sway’;
}, Math.random() * 3000);

requestAnimationFrame(() => {
heart.style.top = ‘-2%’;
heart.style.opacity = 0.5;
heart.style.transform = `rotate(45deg) scale(${Math.random() * 0.4 + 0.8})`;

function removeHeart(event) {
if (event.propertyName === ‘top’) {
heart.parentNode.removeChild(heart);
heart.removeEventListener(‘transitionend’, removeHeart);
}
}

heart.addEventListener(‘transitionend’, removeHeart);
});
}
}

customElements.define(‘valentine-hearts’, ValentineHearts);

Happy Valentine’s Day!

Pin It on Pinterest

Generated by Feedzy