Files
max-richter.dev/src/components/Thumbhash.astro
Max Richter 68431e6b9c
Some checks failed
Deploy to SFTP Server / build (push) Failing after 18m17s
feat: optimize image hash
2024-04-06 22:38:56 +02:00

56 lines
1.5 KiB
Plaintext

<script>
import { thumbHashToRGBA, rgbaToDataURL } from "thumbhash";
function show(img: HTMLImageElement) {
img.style.opacity = "1";
img.style.filter = "blur(0px)";
setTimeout(() => {
if (img.parentNode) {
(img.parentNode as HTMLPictureElement).style.background = "";
}
}, 600);
}
console.log("Thumbhash script loaded");
document.querySelectorAll("[data-thumbhash]").forEach((entry) => {
const parent = entry?.parentNode as HTMLPictureElement;
const img = entry as HTMLImageElement;
if (parent?.nodeName !== "PICTURE") return;
const hash = img.getAttribute("data-thumbhash");
if (!hash) return;
// its only browser, why you have to be mad
const decodedString = window.atob(hash);
// Create Uint8Array from decoded string
const buffer = new Uint8Array(decodedString.length);
for (let i = 0; i < decodedString.length; i++) {
buffer[i] = decodedString.charCodeAt(i);
}
const image = thumbHashToRGBA(buffer);
const dataURL = rgbaToDataURL(image.w, image.h, image.rgba);
parent.style.background = `url(${dataURL})`;
parent.style.backgroundSize = "cover";
if (img.complete) {
return;
}
img.style.opacity = "0";
img.style.filter = "blur(5px)";
img.style.transition = "opacity 0.6s ease, filter 0.8s ease";
const sources = parent.querySelectorAll("source");
img.onload = () => show(img);
for (const source of sources) {
source.addEventListener("load", () => show(img));
}
});
</script>