Skip to content

Commit

Permalink
Add dynamically measured images example
Browse files Browse the repository at this point in the history
Fixes #979
  • Loading branch information
kirill-konshin committed Apr 20, 2018
1 parent f009f93 commit f92e6c3
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions docs/Masonry.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,105 @@ ReactDOM.render(
document.getElementById('example')
);
```

### Masonry example with dynamically measured images

Items in the list in basic example can only be measured once, which means client has to know all the
sizes upfront before displaying. For cases when server cannot deliver such data we need to
pre-measure images. In order to preserve correct optimized layout images can only be displayed one
by one in the order they appear in the array, not in the order they are loaded.

These specifics were taken into account in a small library
[react-virtualized-image-measurer](https://github.com/kirill-konshin/react-virtualized-image-measurer)
here is an example with dynamically measured images:

```js
import React from "react";
import { render } from "react-dom";
import {
CellMeasurer,
CellMeasurerCache,
createMasonryCellPositioner,
Masonry
} from "react-virtualized";
import ImageMeasurer from "react-virtualized-image-measurer";

// Array of images with captions
//const list = [{image: 'http://...', title: 'Foo'}];

// We need to make sure images are loaded from scratch every time for this demo
const noCacheList = list.map(item => ({
...item,
image: item.image + "?noCache=" + Math.random()
}));

const columnWidth = 200;
const defaultHeight = 250;
const defaultWidth = columnWidth;

const MasonryComponent = ({ itemsWithSizes }) => {
// Default sizes help Masonry decide how many images to batch-measure
const cache = new CellMeasurerCache({
defaultHeight,
defaultWidth,
fixedWidth: true
});

// Our masonry layout will use 3 columns with a 10px gutter between
const cellPositioner = createMasonryCellPositioner({
cellMeasurerCache: cache,
columnCount: 3,
columnWidth,
spacer: 10
});

function cellRenderer({ index, key, parent, style }) {
const { item, size } = itemsWithSizes[index];
const height = columnWidth * (size.height / size.width) || defaultHeight;

return (
<CellMeasurer cache={cache} index={index} key={key} parent={parent}>
<div style={style}>
<img
src={item.image}
alt={item.title}
style={{
height: height,
width: columnWidth
}}
/>
<h4>{item.title}</h4>
</div>
</CellMeasurer>
);
}

return (
<Masonry
cellCount={itemsWithSizes.length}
cellMeasurerCache={cache}
cellPositioner={cellPositioner}
cellRenderer={cellRenderer}
height={600}
width={800}
/>
);
};

// Render your grid
render(
<ImageMeasurer
items={noCacheList}
image={item => item.image}
defaultHeight={defaultHeight}
defaultWidth={defaultWidth}
>
{({ itemsWithSizes }) => (
<MasonryComponent itemsWithSizes={itemsWithSizes} />
)}
</ImageMeasurer>,
document.getElementById("root")
);
```

Live demo: https://codesandbox.io/s/7y66p25qv6

0 comments on commit f92e6c3

Please sign in to comment.