From 2625c9c78e51761e27d039dc0ef43769282689b5 Mon Sep 17 00:00:00 2001 From: Jake Runyan Date: Wed, 25 Dec 2024 13:16:32 -1000 Subject: [PATCH] Fix layout scaling when resizing. --- README.md | 1 + package-lock.json | 49 +++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/components/Home.css | 23 +++++++++++++++++++ src/components/Home.js | 38 ++++++++++++++++++++++++++++++-- 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 src/components/Home.css diff --git a/README.md b/README.md index a8fce33..782b0a0 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ npx create-react-app portfolio ``` npm install web-vitals npm install react-router-dom +npm install masonry-layout ``` 3. Test changes/fixes with ``` diff --git a/package-lock.json b/package-lock.json index 62944f7..0051762 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "cra-template": "1.2.0", + "masonry-layout": "^4.2.2", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.1.1", @@ -6407,6 +6408,12 @@ "node": ">= 0.8" } }, + "node_modules/desandro-matches-selector": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz", + "integrity": "sha512-+1q0nXhdzg1IpIJdMKalUwvvskeKnYyEe3shPRwedNcWtnhEKT3ZxvFjzywHDeGcKViIxTCAoOYQWP1qD7VNyg==", + "license": "MIT" + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -7625,6 +7632,12 @@ "node": ">= 0.6" } }, + "node_modules/ev-emitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz", + "integrity": "sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==", + "license": "MIT" + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -7993,6 +8006,15 @@ "node": ">=8" } }, + "node_modules/fizzy-ui-utils": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz", + "integrity": "sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==", + "license": "MIT", + "dependencies": { + "desandro-matches-selector": "^2.0.0" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -8347,6 +8369,12 @@ "node": ">=8.0.0" } }, + "node_modules/get-size": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-size/-/get-size-2.0.3.tgz", + "integrity": "sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==", + "license": "MIT" + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -11047,6 +11075,16 @@ "tmpl": "1.0.5" } }, + "node_modules/masonry-layout": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/masonry-layout/-/masonry-layout-4.2.2.tgz", + "integrity": "sha512-iGtAlrpHNyxaR19CvKC3npnEcAwszXoyJiI8ARV2ePi7fmYhIud25MHK8Zx4P0LCC4d3TNO9+rFa1KoK1OEOaA==", + "license": "MIT", + "dependencies": { + "get-size": "^2.0.2", + "outlayer": "^2.1.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -11634,6 +11672,17 @@ "node": ">= 0.8.0" } }, + "node_modules/outlayer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/outlayer/-/outlayer-2.1.1.tgz", + "integrity": "sha512-+GplXsCQ3VrbGujAeHEzP9SXsBmJxzn/YdDSQZL0xqBmAWBmortu2Y9Gwdp9J0bgDQ8/YNIPMoBM13nTwZfAhw==", + "license": "MIT", + "dependencies": { + "ev-emitter": "^1.0.0", + "fizzy-ui-utils": "^2.0.0", + "get-size": "^2.0.2" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", diff --git a/package.json b/package.json index 9935ba2..3d92134 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "cra-template": "1.2.0", + "masonry-layout": "^4.2.2", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.1.1", diff --git a/src/components/Home.css b/src/components/Home.css new file mode 100644 index 0000000..7f60855 --- /dev/null +++ b/src/components/Home.css @@ -0,0 +1,23 @@ +.gallery { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* Responsive columns */ + margin: 0 auto; /* Adjust for spacing */ +} + +.gallery-photo { + margin: 4px; /* Vertical padding between items */ + margin-left: 4px; /* Horizontal padding between items */ + margin-right: 4px; /* Horizontal padding between items */ + border-radius: 8px; /* Optional: Add rounded corners */ + display: block; /* Ensure images are block elements */ + height: auto; /* Maintain aspect ratio */ + max-width: 30vw; + object-fit: cover; /* Ensure images cover the area without distortion */ +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .gallery-photo { + width: calc(100% - 10px); /* Single column on smaller screens */ + } +} \ No newline at end of file diff --git a/src/components/Home.js b/src/components/Home.js index e78b37a..47e9f58 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -1,6 +1,10 @@ -import React from 'react'; +import React, { useEffect, useRef } from 'react'; +import Masonry from 'masonry-layout'; +import './Home.css'; // Global styles const Home = () => { + const masonryRef = useRef(null); + // Use require.context to load all images from the static/photos directory const importAll = (r) => { let images = {}; @@ -10,8 +14,38 @@ const Home = () => { const images = importAll(require.context('../../static/photos', false, /\.(png|jpe?g|svg)$/)); + useEffect(() => { + // Initialize Masonry after images have loaded + const masonry = new Masonry(masonryRef.current, { + itemSelector: '.gallery-photo', + columnWidth: '.gallery-photo', + percentPosition: true, + horizontalOrder: true, + }); + + // Layout Masonry after all images have loaded + const imgLoad = images => { + const imgLoad = images.map(img => { + return new Promise((resolve) => { + const imgElement = new Image(); + imgElement.src = img; + imgElement.onload = resolve; + }); + }); + return Promise.all(imgLoad); + }; + + imgLoad(Object.values(images)).then(() => { + masonry.layout(); + }); + + return () => { + masonry.destroy(); // Cleanup on unmount + }; + }, [images]); + return ( -
+
{Object.keys(images).map((key, index) => ( {`Jake ))}