Skip to content

Commit e844c15

Browse files
Add responsive image example (#337)
1 parent 90ba3d7 commit e844c15

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import React, { useState, useEffect, useMemo, useCallback } from "react";
2+
3+
import { TransformWrapper } from "../../../components/transform-wrapper";
4+
import { TransformComponent } from "../../../components/transform-component";
5+
import { normalizeArgs } from "stories/utils";
6+
import exampleImg from "../../assets/medium-image.jpg";
7+
8+
export const Example: React.FC<any> = (args: any) => {
9+
const src = exampleImg;
10+
const alt = "example";
11+
const backgroundColor = "black";
12+
const scaleUp = true;
13+
const zoomFactor = 8;
14+
15+
const [container, setContainer] = useState<HTMLDivElement | null>(null);
16+
17+
const [containerWidth, setContainerWidth] = useState<number>(0);
18+
const [containerHeight, setContainerHeight] = useState<number>(0);
19+
20+
const [imageNaturalWidth, setImageNaturalWidth] = useState<number>(0);
21+
const [imageNaturalHeight, setImageNaturalHeight] = useState<number>(0);
22+
23+
const imageScale = useMemo(() => {
24+
if (
25+
containerWidth === 0 ||
26+
containerHeight === 0 ||
27+
imageNaturalWidth === 0 ||
28+
imageNaturalHeight === 0
29+
)
30+
return 0;
31+
const scale = Math.min(
32+
containerWidth / imageNaturalWidth,
33+
containerHeight / imageNaturalHeight,
34+
);
35+
return scaleUp ? scale : Math.max(scale, 1);
36+
}, [
37+
scaleUp,
38+
containerWidth,
39+
containerHeight,
40+
imageNaturalWidth,
41+
imageNaturalHeight,
42+
]);
43+
44+
const handleResize = useCallback(() => {
45+
if (container !== null) {
46+
const rect = container.getBoundingClientRect();
47+
setContainerWidth(rect.width);
48+
setContainerHeight(rect.height);
49+
} else {
50+
setContainerWidth(0);
51+
setContainerHeight(0);
52+
}
53+
}, [container]);
54+
55+
useEffect(() => {
56+
handleResize();
57+
window.addEventListener("resize", handleResize);
58+
return () => {
59+
window.removeEventListener("resize", handleResize);
60+
};
61+
}, [handleResize]);
62+
63+
const handleImageOnLoad = (image: HTMLImageElement) => {
64+
setImageNaturalWidth(image.naturalWidth);
65+
setImageNaturalHeight(image.naturalHeight);
66+
};
67+
68+
useEffect(() => {
69+
const image = new Image();
70+
image.onload = () => handleImageOnLoad(image);
71+
image.src = src;
72+
}, [src]);
73+
74+
return (
75+
<div
76+
style={{
77+
width: "100%",
78+
height: "100%",
79+
backgroundColor,
80+
}}
81+
ref={(el: HTMLDivElement | null) => setContainer(el)}
82+
>
83+
{imageScale > 0 && (
84+
<TransformWrapper
85+
key={`${containerWidth}x${containerHeight}`}
86+
initialScale={imageScale}
87+
minScale={imageScale}
88+
maxScale={imageScale * zoomFactor}
89+
centerOnInit
90+
{...normalizeArgs(args)}
91+
>
92+
<TransformComponent
93+
wrapperStyle={{
94+
width: "100%",
95+
height: "100%",
96+
}}
97+
>
98+
<img alt={alt} src={src} />
99+
</TransformComponent>
100+
</TransformWrapper>
101+
)}
102+
</div>
103+
);
104+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Meta, Story, ArgsTable, Canvas } from "@storybook/addon-docs/blocks";
2+
import { action } from "@storybook/addon-actions";
3+
4+
import { TransformWrapper } from "../../../components/transform-wrapper";
5+
import { argsTypes } from "../../types/args.types";
6+
import { Example } from "./example";
7+
8+
export const Template = (args) => (
9+
<div style={{ width: "80vw", height: "80vh" }}>
10+
<Example {...args} />
11+
</div>
12+
);
13+
14+
<Meta
15+
title="Examples/Responsive Image"
16+
component={TransformWrapper}
17+
argTypes={argsTypes}
18+
/>
19+
20+
# Responsive Image
21+
22+
<br />
23+
24+
### Preview:
25+
26+
<Canvas>
27+
<Story name="Responsive Image">{(args) => <Template {...args} />}</Story>
28+
</Canvas>
29+
30+
## Component API
31+
32+
<ArgsTable story="Responsive Image" />

0 commit comments

Comments
 (0)