Adds placeholder during image loading (#5120

* Adds placeholder during image loading

* Small refactor
This commit is contained in:
Tom Moor
2023-03-29 23:12:55 -04:00
committed by GitHub
parent 381d640719
commit ec3ebb91c0

View File

@@ -24,6 +24,7 @@ const Image = (
const [contentWidth, setContentWidth] = React.useState( const [contentWidth, setContentWidth] = React.useState(
() => document.body.querySelector("#full-width-container")?.clientWidth || 0 () => document.body.querySelector("#full-width-container")?.clientWidth || 0
); );
const [loaded, setLoaded] = React.useState(false);
const [naturalWidth, setNaturalWidth] = React.useState(node.attrs.width); const [naturalWidth, setNaturalWidth] = React.useState(node.attrs.width);
const [naturalHeight, setNaturalHeight] = React.useState(node.attrs.height); const [naturalHeight, setNaturalHeight] = React.useState(node.attrs.height);
const [size, setSize] = React.useState({ const [size, setSize] = React.useState({
@@ -175,7 +176,10 @@ const Image = (
)} )}
<ImageZoom zoomMargin={24}> <ImageZoom zoomMargin={24}>
<img <img
style={widthStyle} style={{
...widthStyle,
display: loaded ? "block" : "none",
}}
src={sanitizeUrl(src) ?? ""} src={sanitizeUrl(src) ?? ""}
onLoad={(ev: React.SyntheticEvent<HTMLImageElement>) => { onLoad={(ev: React.SyntheticEvent<HTMLImageElement>) => {
// For some SVG's Firefox does not provide the naturalWidth, in this // For some SVG's Firefox does not provide the naturalWidth, in this
@@ -185,6 +189,7 @@ const Image = (
const nh = (ev.target as HTMLImageElement).naturalHeight; const nh = (ev.target as HTMLImageElement).naturalHeight;
setNaturalWidth(nw); setNaturalWidth(nw);
setNaturalHeight(nh); setNaturalHeight(nh);
setLoaded(true);
if (!node.attrs.width) { if (!node.attrs.width) {
setSize((state) => ({ setSize((state) => ({
@@ -194,6 +199,15 @@ const Image = (
} }
}} }}
/> />
<img
style={{
...widthStyle,
display: loaded ? "none" : "block",
}}
src={`data:image/svg+xml;charset=UTF-8,${encodeURIComponent(
getPlaceholder(size.width, size.height)
)}`}
/>
</ImageZoom> </ImageZoom>
{isEditable && !isFullWidth && isResizable && ( {isEditable && !isFullWidth && isResizable && (
<> <>
@@ -215,6 +229,10 @@ const Image = (
); );
}; };
function getPlaceholder(width: number, height: number) {
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" />`;
}
export const Caption = styled.p` export const Caption = styled.p`
border: 0; border: 0;
display: block; display: block;