Skip to content

Commit 3a22c0f

Browse files
Add dynamically measured images example
Fixes #979
1 parent f009f93 commit 3a22c0f

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

docs/Masonry.md

+101
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,104 @@ ReactDOM.render(
197197
document.getElementById('example')
198198
);
199199
```
200+
201+
### Masonry example with dynamically measured images
202+
203+
Items in the list in basic example can only be measured once, which means client has to know all the
204+
sizes upfront before displaying. For cases when server cannot deliver such data we need to
205+
pre-measure images. In order to preserve correct optimized layout images can only be displayed one
206+
by one in the order they appear in the array, not in the order they are loaded.
207+
208+
These specifics were taken into account in a small library `react-virtualized-image-measurer`,
209+
here is an example with dynamically measured images:
210+
211+
```js
212+
import React from "react";
213+
import { render } from "react-dom";
214+
import {
215+
CellMeasurer,
216+
CellMeasurerCache,
217+
createMasonryCellPositioner,
218+
Masonry
219+
} from "react-virtualized";
220+
import ImageMeasurer from "react-virtualized-image-measurer";
221+
222+
// Array of images with captions
223+
//const list = [{image: 'http://...', title: 'Foo'}];
224+
225+
// We need to make sure images are loaded from scratch every time for this demo
226+
const noCacheList = list.map(item => ({
227+
...item,
228+
image: item.image + "?noCache=" + Math.random()
229+
}));
230+
231+
const columnWidth = 200;
232+
const defaultHeight = 250;
233+
const defaultWidth = columnWidth;
234+
235+
const MasonryComponent = ({ itemsWithSizes }) => {
236+
// Default sizes help Masonry decide how many images to batch-measure
237+
const cache = new CellMeasurerCache({
238+
defaultHeight,
239+
defaultWidth,
240+
fixedWidth: true
241+
});
242+
243+
// Our masonry layout will use 3 columns with a 10px gutter between
244+
const cellPositioner = createMasonryCellPositioner({
245+
cellMeasurerCache: cache,
246+
columnCount: 3,
247+
columnWidth,
248+
spacer: 10
249+
});
250+
251+
function cellRenderer({ index, key, parent, style }) {
252+
const { item, size } = itemsWithSizes[index];
253+
const height = columnWidth * (size.height / size.width) || defaultHeight;
254+
255+
return (
256+
<CellMeasurer cache={cache} index={index} key={key} parent={parent}>
257+
<div style={style}>
258+
<img
259+
src={item.image}
260+
alt={item.title}
261+
style={{
262+
height: height,
263+
width: columnWidth
264+
}}
265+
/>
266+
<h4>{item.title}</h4>
267+
</div>
268+
</CellMeasurer>
269+
);
270+
}
271+
272+
return (
273+
<Masonry
274+
cellCount={itemsWithSizes.length}
275+
cellMeasurerCache={cache}
276+
cellPositioner={cellPositioner}
277+
cellRenderer={cellRenderer}
278+
height={600}
279+
width={800}
280+
/>
281+
);
282+
};
283+
284+
// Render your grid
285+
render(
286+
<ImageMeasurer
287+
items={noCacheList}
288+
image={item => item.image}
289+
defaultHeight={defaultHeight}
290+
defaultWidth={defaultWidth}
291+
>
292+
{({ itemsWithSizes }) => (
293+
<MasonryComponent itemsWithSizes={itemsWithSizes} />
294+
)}
295+
</ImageMeasurer>,
296+
document.getElementById("root")
297+
);
298+
```
299+
300+
Live demo: https://codesandbox.io/s/7y66p25qv6

0 commit comments

Comments
 (0)