Refactoring parallax background
This commit is contained in:
@@ -710,3 +710,7 @@ We have already done some of the work for this with our dynamic scrolling.
|
||||
**The plan**
|
||||
|
||||
We are going to create additional _background_ layers that will be layered on top of the actual background. We will update our JavaScript scroll event listener to control the scroll speed of each of these layers. Finally we will use CSS to ensure the layers are styled correctly to get our parallax effect.
|
||||
|
||||
First I tried adding additional layers to the body however this proved difficult to control the position on various screen sizes.
|
||||
|
||||
|
||||
|
||||
@@ -233,15 +233,16 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="page-bottom-section"></section>
|
||||
<section id="credits" class="credits-section">
|
||||
<div class="credits-box">
|
||||
<div class="title-text">
|
||||
<p>I made this website! Copyright Jesse M. Ellis 2024 😊</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<section id="credits" class="credits-section">
|
||||
<div class="parallax-layer layer-1"></div>
|
||||
<div class="parallax-layer layer-2"></div>
|
||||
<div class="parallax-layer layer-3"></div>
|
||||
<div class="credits-box">
|
||||
<div class="title-text">
|
||||
<p>I made this website! Copyright Jesse M. Ellis 2024 😊</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -15,15 +15,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
const titleBox = document.querySelector(".title-box");
|
||||
const aboutSection = document.querySelector("#about");
|
||||
const contactSection = document.querySelector("#contact");
|
||||
const creditsSection = document.querySelector("#credits");
|
||||
const parallaxlayer1 = document.querySelector(".layer-1");
|
||||
const parallaxlayer2 = document.querySelector(".layer-2");
|
||||
const parallaxlayer3 = document.querySelector(".layer-3");
|
||||
|
||||
const scrollY = window.scrollY;
|
||||
const aboutTop = aboutSection.getBoundingClientRect().top + scrollY;
|
||||
const contactTop = contactSection.getBoundingClientRect().top + scrollY;
|
||||
const sectionTop = creditsSection.offsetTop;
|
||||
const slowScrollRate = 0.5;
|
||||
|
||||
// Get viewport height for parallax background offsets
|
||||
const viewportHeight = window.innerHeight;
|
||||
|
||||
// Move title-box if it's above the viewport and not yet touching about-section
|
||||
if (scrollY < aboutTop) {
|
||||
const opacity1 = scrollY / aboutTop;
|
||||
titleBox.style.transform = `translateY(${scrollY * slowScrollRate}px)`;
|
||||
@@ -33,32 +35,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
titleBox.style.opacity = 0;
|
||||
}
|
||||
|
||||
// Adjust navbar opacity when below the contact section
|
||||
const contactBottom = contactTop + contactSection.offsetHeight;
|
||||
if (scrollY > contactBottom) {
|
||||
// Calculate opacity based on how far below the contact section we are
|
||||
const fadeDistance = 100;
|
||||
const distanceBelow = scrollY - contactBottom;
|
||||
const opacity2 = Math.max(1 - distanceBelow / fadeDistance, 0);
|
||||
navBar.style.opacity = opacity2;
|
||||
if (scrollY > contactTop) {
|
||||
const opacity2 = (scrollY - contactTop) / (document.body.scrollHeight - contactTop);
|
||||
navBar.style.opacity = Math.max(1 - opacity2, 0.5);
|
||||
} else {
|
||||
navBar.style.opacity = 1;
|
||||
}
|
||||
|
||||
// Parallax background scroll rates
|
||||
const body = document.body;
|
||||
const bridgeScrollRate = 0.4;
|
||||
const treesScrollRate = 0.5;
|
||||
const castleScrollRate = 0.7;
|
||||
const cloudsScrollRate = 0.9;
|
||||
|
||||
body.style.backgroundPosition = `
|
||||
left ${scrollY * bridgeScrollRate + viewportHeight * 3.05}px,
|
||||
left ${scrollY * treesScrollRate + viewportHeight * 2.55}px,
|
||||
left ${scrollY * castleScrollRate + viewportHeight * 1.5}px,
|
||||
left ${scrollY * cloudsScrollRate + viewportHeight * 0.4}px,
|
||||
left 0px
|
||||
`;
|
||||
const relativeScrollY = sectionTop - scrollY;
|
||||
parallaxlayer1.style.transform = `translateY(${relativeScrollY * 0.2}px)`;
|
||||
parallaxlayer2.style.transform = `translateY(${relativeScrollY * 0.4}px)`;
|
||||
parallaxlayer3.style.transform = `translateY(${relativeScrollY * 0.6}px)`;
|
||||
});
|
||||
|
||||
// Function to load text from a file into an html component
|
||||
@@ -120,12 +107,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
document
|
||||
.getElementById("contact-form")
|
||||
.addEventListener("submit", async function (event) {
|
||||
// Take control of form submission
|
||||
event.preventDefault();
|
||||
const form = event.target;
|
||||
const formData = new FormData(form);
|
||||
try {
|
||||
// Submit the form data using the Fetch API and catch response
|
||||
const response = await fetch(form.action, {
|
||||
method: form.method,
|
||||
body: formData,
|
||||
@@ -134,15 +119,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
},
|
||||
});
|
||||
if (response.ok) {
|
||||
// Success! give user a message
|
||||
alert("Thank you! Your message has been sent.");
|
||||
form.reset(); // Clear the form
|
||||
form.reset();
|
||||
} else {
|
||||
// Fail :( give user a message
|
||||
alert("Oops! There was a problem submitting your form.");
|
||||
}
|
||||
} catch (error) {
|
||||
// Log any errors
|
||||
console.error("Error:", error);
|
||||
alert(
|
||||
"There was a problem submitting your form. Please try again later."
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-image: url("../images/Bridge.png"), url("../images/Trees.png"),
|
||||
url("../images/Castle.png"), url("../images/Clouds.png"),
|
||||
url("../images/Moon.png");
|
||||
background-size: auto, auto, auto, auto, cover;
|
||||
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat;
|
||||
background-attachment: scroll, scroll, scroll, scroll, fixed;
|
||||
background-position: left 300vh, left 300vh, left 300vh, left 350vh, left top;
|
||||
background-image: url("../images/Moon.png");
|
||||
background-size: cover;
|
||||
background-position: left;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
min-width: 768px;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
max-width: 1440px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
@@ -79,25 +76,7 @@ body {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.page-bottom-section {
|
||||
height: 90vh;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.credits-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.credits-box {
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 1);
|
||||
border-radius: 100px;
|
||||
width: 400px;
|
||||
padding: 10px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.title-box {
|
||||
display: flex;
|
||||
@@ -410,6 +389,10 @@ button:hover {
|
||||
|
||||
/* Contact Form */
|
||||
|
||||
.contact-section {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.contact-box {
|
||||
margin-top: 10rem;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
@@ -472,6 +455,60 @@ button[type="reset"] {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Credits Section - parallax background */
|
||||
|
||||
.credits-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
min-width: 768px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.credits-section .parallax-layer {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.credits-box {
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, 1);
|
||||
border-radius: 100px;
|
||||
width: 400px;
|
||||
padding: 10px;
|
||||
margin-bottom: 5rem;
|
||||
}
|
||||
|
||||
.parallax-layer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: left;
|
||||
background-repeat: no-repeat;
|
||||
min-width: 768px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.layer-1 {
|
||||
background-image: url('images/Clouds.png');
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.layer-2 {
|
||||
background-image: url('images/Trees.png');
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.layer-3 {
|
||||
background-image: url('images/Bridge.png');
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Media Queries */
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
@@ -525,3 +562,10 @@ button[type="reset"] {
|
||||
padding-right: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.parallax-layer {
|
||||
height: 120%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user