diff options
author | Starfall <us@starfall.systems> | 2020-07-11 12:31:22 -0500 |
---|---|---|
committer | Starfall <us@starfall.systems> | 2020-07-11 12:31:22 -0500 |
commit | 2f20bc2a8275875033c97249825a2a3305980c3b (patch) | |
tree | 079a021ab1ce792a40555e0718f9861ee8b53f7a /app/javascript/flavours/glitch/components/blurhash.js | |
parent | 816d10c7eecd83cb0f115c10328cbb504dabc7e9 (diff) | |
parent | 7a23347db5be3f262dbcafbecf768588dc648bda (diff) |
Merge branch 'glitch' into main
Diffstat (limited to 'app/javascript/flavours/glitch/components/blurhash.js')
-rw-r--r-- | app/javascript/flavours/glitch/components/blurhash.js | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/components/blurhash.js b/app/javascript/flavours/glitch/components/blurhash.js new file mode 100644 index 000000000..2af5cfc56 --- /dev/null +++ b/app/javascript/flavours/glitch/components/blurhash.js @@ -0,0 +1,65 @@ +// @ts-check + +import { decode } from 'blurhash'; +import React, { useRef, useEffect } from 'react'; +import PropTypes from 'prop-types'; + +/** + * @typedef BlurhashPropsBase + * @property {string?} hash Hash to render + * @property {number} width + * Width of the blurred region in pixels. Defaults to 32 + * @property {number} [height] + * Height of the blurred region in pixels. Defaults to width + * @property {boolean} [dummy] + * Whether dummy mode is enabled. If enabled, nothing is rendered + * and canvas left untouched + */ + +/** @typedef {JSX.IntrinsicElements['canvas'] & BlurhashPropsBase} BlurhashProps */ + +/** + * Component that is used to render blurred of blurhash string + * + * @param {BlurhashProps} param1 Props of the component + * @returns Canvas which will render blurred region element to embed + */ +function Blurhash({ + hash, + width = 32, + height = width, + dummy = false, + ...canvasProps +}) { + const canvasRef = /** @type {import('react').MutableRefObject<HTMLCanvasElement>} */ (useRef()); + + useEffect(() => { + const { current: canvas } = canvasRef; + canvas.width = canvas.width; // resets canvas + + if (dummy || !hash) return; + + try { + const pixels = decode(hash, width, height); + const ctx = canvas.getContext('2d'); + const imageData = new ImageData(pixels, width, height); + + ctx.putImageData(imageData, 0, 0); + } catch (err) { + console.error('Blurhash decoding failure', { err, hash }); + } + }, [dummy, hash, width, height]); + + return ( + <canvas {...canvasProps} ref={canvasRef} width={width} height={height} /> + ); +} + +Blurhash.propTypes = { + hash: PropTypes.string.isRequired, + width: PropTypes.number, + height: PropTypes.number, + dummy: PropTypes.bool, +}; + +export default React.memo(Blurhash); |