diff --git a/__test__/__snapshots__/Gallery.test.js.snap b/__test__/__snapshots__/Gallery.test.js.snap index 290171a..023a452 100644 --- a/__test__/__snapshots__/Gallery.test.js.snap +++ b/__test__/__snapshots__/Gallery.test.js.snap @@ -3,6 +3,7 @@ exports[`Gallery it matches correct snapshot 1`] = ` number | undefined | Optional. The algorithm will do its best to have rows close to this value. The smaller the number, the shorter the row, the more photos will be in a row. +justifyLastRow | bool | true | Optional. If there are enough photos to fill the container, stretch them to make it fill. Be sure to use the targetRowHeight option otherwise it won't work. limitNodeSearch | number or (containerWidth) => number | undefined | Optional. Ignored if `direction=column`. Limit how many neighboring nodes to search for when visiting a node to find the best node or photo to break on. The Gallery decides this for you by default, using an algorithm that determines the probably average photo per row by looking at `targetRowHeight` and `containerWidth` and then adding 8. If it isn't limited the gallery would take too long to calculate and it would be looking at nodes that it would not make sense to break on, making unnecessary calculations. For example if we are currently visiting photo #2 we do not need to check if photo #200 is a good place to break because it is likely we will never have that many photos in a row. The smaller the number, the faster your gallery will calculate. Images per row cannot exceed this amount, so its one way of limiting that, but then it will not be able to search ahead for better fits. Use `targetRowHeight` as a way of adjusting the amount of photos if you want more/less photos per row. If you find your graph is slow, you can make this number smaller. If you pass in a function you will receive the `containerWidth` as a parameter. If your `containerWidth` is small and you only want 1 or 2 photos per row, it makes sense to make this number smaller at these breakpoints to speed things up. It is recommended you use the default setting unless you understage its usage. onClick | function | undefined | Optional. Do something when the user clicks a photo. Receives arguments event and an object containing the index, Photos 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 diff --git a/src/Gallery.js b/src/Gallery.js index b5475d9..71457d8 100644 --- a/src/Gallery.js +++ b/src/Gallery.js @@ -15,6 +15,7 @@ const Gallery = React.memo(function Gallery({ targetRowHeight, columns, renderImage, + justifyLastRow }) { const [containerWidth, setContainerWidth] = useState(0); const galleryEl = useRef(null); @@ -71,7 +72,7 @@ const Gallery = React.memo(function Gallery({ } galleryStyle = { display: 'flex', flexWrap: 'wrap', flexDirection: 'row' }; - thumbs = computeRowLayout({ containerWidth: width, limitNodeSearch, targetRowHeight, margin, photos }); + thumbs = computeRowLayout({ containerWidth: width, limitNodeSearch, targetRowHeight, margin, photos, justifyLastRow }); } if (direction === 'column') { // allow user to calculate columns from containerWidth @@ -122,12 +123,14 @@ Gallery.propTypes = { limitNodeSearch: PropTypes.oneOfType([PropTypes.func, PropTypes.number]), margin: PropTypes.number, renderImage: PropTypes.func, + justifyLastRow: PropTypes.bool }; Gallery.defaultProps = { margin: 2, direction: 'row', targetRowHeight: 300, + justifyLastRow: true }; export { Photo }; export default Gallery; diff --git a/src/layouts/justified.js b/src/layouts/justified.js index e6615c4..c3899c3 100644 --- a/src/layouts/justified.js +++ b/src/layouts/justified.js @@ -31,15 +31,24 @@ const makeGetNeighbors = (targetHeight, containerWidth, photos, limitNodeSearch, return results; }; -export const computeRowLayout = ({ containerWidth, limitNodeSearch, targetRowHeight, margin, photos }) => { +export const computeRowLayout = ({ containerWidth, limitNodeSearch, targetRowHeight, margin, photos, justifyLastRow }) => { // const t = +new Date(); const getNeighbors = makeGetNeighbors(targetRowHeight, containerWidth, photos, limitNodeSearch, margin); let path = findShortestPath(getNeighbors, '0', photos.length); path = path.map(node => +node); + + const totalRows = path.length - 1; + // console.log(`time to find the shortest path: ${(+new Date() - t)} ms`); for (let i = 1; i < path.length; ++i) { const row = photos.slice(path[i - 1], path[i]); const height = getCommonHeight(row, containerWidth, margin); + const isLastRow = i === totalRows; + + if (!justifyLastRow && isLastRow && height > targetRowHeight) { + height = targetRowHeight; + } + for (let j = path[i - 1]; j < path[i]; ++j) { photos[j].width = round(height * ratio(photos[j]), 1); photos[j].height = height;