Skip to content

Commit

Permalink
Add dynamically measured images example (#1081)
Browse files Browse the repository at this point in the history
Fixes #979
  • Loading branch information
kirill-konshin authored and wuweiweiwu committed May 11, 2018
1 parent 3bc6498 commit ccc2a52
Showing 1 changed file with 103 additions and 0 deletions.
103 changes: 103 additions & 0 deletions docs/Masonry.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,106 @@ 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;

// 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
});

const MasonryComponent = ({ itemsWithSizes }) => {

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 ccc2a52

Please sign in to comment.