Skip to content

Commit

Permalink
Merge pull request #132 from neptunian/v7
Browse files Browse the repository at this point in the history
V7
  • Loading branch information
neptunian authored Apr 20, 2019
2 parents d972e9d + 8cd952a commit da0a70e
Show file tree
Hide file tree
Showing 24 changed files with 1,554 additions and 2,034 deletions.
71 changes: 22 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,38 @@

* Responsive, accessible, composable, and customizable image gallery component
* Maintains the original aspect ratio of your photos
* Creates a masonry style layout
* Uses actual image elements, optionally pass in srcSet and sizes attributes
* Creates a masonry or justified grid
* Supports row or column direction layout
* Supports passing in a custom image component for implementation of things like image selection, favorites, captions, or whatever your little heart desires!
* Provides an image renderer for custom implementation of things like image selection, favorites, captions, etc.
* SSR app compatible

## Preview
<img src="https://c1.staticflickr.com/5/4914/46923523161_5e729d8313_h.jpg" />

## Installation
| Row | Column |
| ------------- |:-------------:|
| <img src="https://live.staticflickr.com/65535/40680327133_6f6218bfa3.jpg" /> | <img src="https://live.staticflickr.com/65535/47594180212_0dc2694eda.jpg"> |


To install:
## Installation

```
yarn add react-photo-gallery
```

## Documentation and Examples
## API Documentation

[http://neptunian.github.io/react-photo-gallery/](http://neptunian.github.io/react-photo-gallery/)

## Direct CodeSandbox Links with Examples and Use Cases
## CodeSandbox Demos with Example Use Cases

* [Basic Row Layout](https://codesandbox.io/s/9yx911wl9y)
* [Basic Column Layout](https://codesandbox.io/s/r09k1xj614)
* [With Lightbox](https://codesandbox.io/s/5vn3lvz2n4)
* [Custom Dynamic Columns](https://codesandbox.io/s/ll7ym48027)
* [Selection using custom ImageComponent](https://codesandbox.io/s/o7o241q09)
* [Dynamic Columns Using columns prop](https://codesandbox.io/s/ll7ym48027)
* [Selection using custom renderImage](https://codesandbox.io/s/o7o241q09)
* [Sortable with drag and drop](https://codesandbox.io/s/8y7n1r9y5j)

To build some examples locally, run:
To build some examples locally, git clone and run:

```
yarn install
Expand All @@ -49,7 +50,7 @@ yarn start
Then open [`localhost:8000`](http://localhost:8000) in a browser.


## Use
## Minimal Setup Example

```jsx

Expand All @@ -70,40 +71,12 @@ const photos = [

```

### Gallery properties

Property | Type | Default | Description
:-----------------------|:--------------|:--------------|:--------------------------------
photos | array | undefined | required; array of objects
columns | number or function | undefined | optional; number of photos per row or a function which receives the container width and should return the desired number of photos per row; defaults to Gallery's breakpoint choosing
onClick | function | undefined | optional; do something when the user clicks a photo; receives arguments event and an object containing the index, photo obj originally sent and the next and previous photos in the gallery if they exist
margin | number | 2 | optional; number of margin pixels around each entire image
direction | string | 'row' | optional; `column` or `row` based layout
ImageComponent | function | default component | optional; use a different image component than the default provided to display your photo

### Photos array item properties (passed into Gallery's photos property)

Property | Type | Default | Description
:-----------------------|:--------------|:--------------|:--------------------------------
src | string | undefined | required; the img src attribute value of the image
srcSet | array or string | undefined | optional; srcSet attribute of the image
sizes | array or string | undefined | optional; sizes attribute of the image
width | number | undefined | required; original width of the gallery image (only used for calculating aspect ratio)
height | number | undefined | required; original height of the gallery image (only used for calculating aspect ratio)
alt | string | undefined | optional; alt text of the gallery image
key | string | src | optional; key to be used on component

### ImageComponent props

If you're passing a function component to ImageComponent you will receive back these props:


Property | Type | Value
:-----------------------|:--------------|:--------------
margin | string | optional; margin prop optionally passed into Gallery by user
index | number | required; the index of the photo within the Gallery
photo | object | required; the individual object passed into Gallery's `photos` array prop, with all the same props except recalculated height and width
direction | string | optional; direction passed into Gallery
top | number | required if direction is 'column'; top position of this image, only passed if direction prop was 'column'
left | number | required if direction is 'column'; left position of this image, only passed if direction prop was 'column'
onClick | function | optional; the onClick function optionally passsed into Gallery by user
## How It Works

### Row Layout
This layout uses an algorithm adapted from the Knuth and Plass line breaking algorithm. It uses a graph to calculate the single best layout where each photo to break on is represented by a node and each edge is represented by a row. The cost of the edge is determined by the user provided `targetRowHeight` vs the row height calculated if it were to break on this node/photo. What you end up with is a layout with rows that are similar in height and photos that are not being stretched or shrunken abnormally as is what happens in a naive implementation. This solves the issue of panoramas shrinking rows or having stragglers or stretched images at the last row, instead creating a justified grid. To make sure it's speedy the graph is being built as the shortest path is being calculated so the entire adjacency list is not calculated ahead of time. You can control how many neighboring nodes that Dijkistra's algorithm will search when it's visiting a node by adjusting the `limitNodeSearch` property, but it's recommended you use the default algorithm. See documentation for recommendations.

Inspired by [this blog article](http://blog.vjeux.com/2014/image/google-plus-layout-find-best-breaks.html) and this [Google Photos blog article](https://medium.com/google-design/google-photos-45b714dfbed1) (under 2. Justified Gallery).

### Column Layout
Goes through each column looking for the best place to insert the next photo by finding the shortest column. Not recommended for panorama aspect ratios.
2 changes: 1 addition & 1 deletion __test__/Gallery.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('Gallery', () => {
it('renders correctly with a column function', () => {
const columns = jest.fn(_ => 3);
wrapper = mount(
<Gallery photos={photos} onClick={handleClick} columns={columns}/>
<Gallery photos={photos} onClick={handleClick} columns={columns} direction="column" />
);
wrapper.setState({containerWidth: 1139})
expect(columns).toBeCalledWith(1139);
Expand Down
Loading

0 comments on commit da0a70e

Please sign in to comment.