import {
html,
css,
customElement,
LitElement,
property,
query,
} from 'lit-element';
import {decode} from '@fpapado/blurhash';
@customElement('blurhash-img')
export class BlurhashImg extends LitElement {
/* Layout notes:
* Images keep their aspect ratio after they are replaced.
* To make the layout of this component analogous, we use an
* --aspect-ratio CSS Custom Property.
*/
static styles = css`
:host {
display: block;
max-width: 100%;
}
.wrapper {
position: relative;
height: 0;
padding-bottom: calc(var(--aspect-ratio) * 100%);
}
canvas {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
`;
/**
* The encoded blurhash, as a string.
*/
@property({type: String}) hash: string | undefined;
/**
* The X-axis resolution in which the decoded image will be rendered at. Recommended min. 32px. Large sizes (>128px) will greatly decrease rendering performance.
*/
@property({type: Number}) resolutionX: number = 32;
/**
* The Y-axis resolution in which the decoded image will be rendered at. Recommended min. 32px. Large sizes (>128px) will greatly decrease rendering performance.
*/
@property({type: Number}) resolutionY: number = 32;
@query('canvas') canvas: HTMLCanvasElement | undefined;
__updateCanvasImage() {
if (this.hash) {
try {
const pixels = decode(this.hash, this.resolutionX, this.resolutionY);
// Set the pixels to the canvas
const imageData = new ImageData(
pixels,
this.resolutionX,
this.resolutionY
);
const canvasEl = this.canvas;
if (canvasEl) {
const ctx = canvasEl.getContext('2d');
if (ctx) {
ctx.putImageData(imageData, 0, 0);
}
}
} catch (error) {
console.log(error);
}
}
}
firstUpdated() {
this.__updateCanvasImage();
}
updated(changedProperties: Map) {
if (
changedProperties.get('hash') ||
changedProperties.get('resolutionX') ||
changedProperties.get('resolutionY')
) {
this.__updateCanvasImage();
}
}
render() {
return html`
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'blurhash-img': BlurhashImg;
}
}