Use Imgur as host instead
@ -5,13 +5,11 @@
|
||||
}
|
||||
|
||||
.gallery-photo {
|
||||
margin: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
border-radius: 8px;
|
||||
margin: 0.6vw;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
height: auto;
|
||||
max-width: 30vw; /* Do not mix with max-height! */
|
||||
max-width: 31vw; /* Do not mix with max-height! */
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
|
@ -1,53 +1,40 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import Masonry from 'masonry-layout';
|
||||
import './Home.css'; // Global styles
|
||||
import images from '../data/Images'; // Import the image URLs
|
||||
import './Home.css'; // Ensure you have your CSS for styling
|
||||
|
||||
const Home = () => {
|
||||
const masonryRef = useRef(null);
|
||||
|
||||
// Use require.context to load all images from the static/photos directory
|
||||
const importAll = (r) => {
|
||||
let images = {};
|
||||
r.keys().forEach((item) => { images[item.replace('./', '')] = r(item); });
|
||||
return images;
|
||||
};
|
||||
|
||||
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,
|
||||
percentPosition: 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);
|
||||
// Layout Masonry after images have loaded
|
||||
const imagesLoaded = () => {
|
||||
masonry.layout();
|
||||
};
|
||||
|
||||
imgLoad(Object.values(images)).then(() => {
|
||||
masonry.layout();
|
||||
// Add event listener for image load
|
||||
const imgElements = masonryRef.current.querySelectorAll('img');
|
||||
imgElements.forEach(img => {
|
||||
img.addEventListener('load', imagesLoaded);
|
||||
});
|
||||
|
||||
return () => {
|
||||
masonry.destroy(); // Cleanup on unmount
|
||||
imgElements.forEach(img => {
|
||||
img.removeEventListener('load', imagesLoaded);
|
||||
});
|
||||
};
|
||||
}, [images]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="gallery" ref={masonryRef}>
|
||||
{Object.keys(images).map((key, index) => (
|
||||
<img key={index} src={images[key]} alt={`Jake Runyan ${index + 1}`} className="gallery-photo" />
|
||||
{images.map((image, index) => (
|
||||
<img key={index} src={image} alt={`Jake Runyan ${index + 1}`} className="gallery-photo" />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
34
src/components/Navbar.css
Normal file
@ -0,0 +1,34 @@
|
||||
.navbar {
|
||||
display: flex;
|
||||
justify-content: space-between; /* Space between logo, title, and icons */
|
||||
align-items: center; /* Center items vertically */
|
||||
background-color: #333; /* Background color of the navbar */
|
||||
padding: 10px 20px; /* Padding for the navbar */
|
||||
}
|
||||
|
||||
.navbar-logo .logo {
|
||||
height: 50px; /* Set a height for the logo */
|
||||
border-radius: 10px; /* Rounded corners for the logo */
|
||||
}
|
||||
|
||||
.navbar-title h1 {
|
||||
color: white; /* Text color */
|
||||
font-family: 'Arial', sans-serif; /* Specify your desired font */
|
||||
font-size: 24px; /* Font size for the title */
|
||||
margin: 0; /* Remove default margin */
|
||||
}
|
||||
|
||||
.navbar-icons {
|
||||
display: flex; /* Use flexbox for icons */
|
||||
gap: 15px; /* Space between icons */
|
||||
}
|
||||
|
||||
.navbar-icons .icon {
|
||||
height: 30px; /* Set a height for the icons */
|
||||
width: 30px; /* Set a width for the icons */
|
||||
transition: transform 0.2s; /* Smooth transition for hover effect */
|
||||
}
|
||||
|
||||
.navbar-icons .icon:hover {
|
||||
transform: scale(1.1); /* Scale up the icon on hover */
|
||||
}
|
@ -1,13 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './Navbar.css';
|
||||
import logo from './static/navbar-logo.png';
|
||||
|
||||
const Navbar = () => {
|
||||
return (
|
||||
<nav>
|
||||
<ul>
|
||||
<li><Link to="/">Home</Link></li>
|
||||
<li><Link to="/contact">Contact</Link></li>
|
||||
</ul>
|
||||
<nav className="navbar">
|
||||
<div className="navbar-logo">
|
||||
<Link to="/">
|
||||
<img src={logo} alt="Logo" className="logo" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="navbar-title">
|
||||
<h1>Photography Portfolio</h1>
|
||||
</div>
|
||||
<div className="navbar-icons">
|
||||
<a href="https://github.com/yourusername" target="_blank" rel="noopener noreferrer">
|
||||
<img src="path/to/github-icon.png" alt="GitHub" className="icon" />
|
||||
</a>
|
||||
<a href="https://www.instagram.com/yourusername" target="_blank" rel="noopener noreferrer">
|
||||
<img src="path/to/instagram-icon.png" alt="Instagram" className="icon" />
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
BIN
src/components/static/navbar-logo.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
8
src/data/Images.js
Normal file
@ -0,0 +1,8 @@
|
||||
/* Images are loaded from urls to avoid checking everything in to git. */
|
||||
const images = [
|
||||
"https://i.imgur.com/OA575Dq.jpg",
|
||||
"https://i.imgur.com/OA575Dq.jpg",
|
||||
"https://i.imgur.com/OA575Dq.jpg",
|
||||
];
|
||||
|
||||
export default images;
|
Before Width: | Height: | Size: 12 MiB |
Before Width: | Height: | Size: 19 MiB |
Before Width: | Height: | Size: 11 MiB |
Before Width: | Height: | Size: 10 MiB |
Before Width: | Height: | Size: 11 MiB |
Before Width: | Height: | Size: 5.7 MiB |
Before Width: | Height: | Size: 15 MiB |
Before Width: | Height: | Size: 25 MiB |
Before Width: | Height: | Size: 25 MiB |
Before Width: | Height: | Size: 24 MiB |