Change Image on Scroll Position
You can use the onScroll
event to listen for scrolling, check at what position the scrollbar is and make the image change or whatever your heart desires. You can read more about onScroll event here. A basic code will be something like this:
var onScrollHandler = function() {
var newImageUrl = yourImageElement.src;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (scrollTop > 100) {
newImageUrl = "img1.jpg"
}
if (scrollTop > 200) {
newImageUrl = "img2.jpg"
}
if (scrollTop > 300) {
newImageUrl = "img3.jpg"
}
yourImageElement.src = newImageUrl;
};
object.addEventListener ("scroll", onScrollHandler);
Of course yourImageElement
should be replaced with the image element you want to change.
If you have jQuery availble you can use the .scroll()
method instead of the event listener and the .scrollTop()
to get the scrollbar position.
Also, you might want to look at some scroll/paralex libraries like skrollr.
Changing Image position when scrolling page
You can achieve the same behavior using css's sticky property
.ImageTesting {
position: -webkit-sticky; /* safary */
position: sticky;
top: 0;
}
Replace an img src on scroll
To replace image source you may use jQuery .attr
method:
var initialSrc = "img/logo.svg";
var scrollSrc = "img/logo-text-black.svg";
$(window).scroll(function() {
var value = $(this).scrollTop();
if (value > 100)
$(".logo").attr("src", scrollSrc);
else
$(".logo").attr("src", initialSrc);
});
This approach requires only one <img>
with logo
class in the HTML:
<nav class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<a href="#top"><img class="logo" src="img/logo.svg"></a>
</div>
</nav>
Improving scroll effect with one side scroll and the other change image based on scroll position
To achieve your goal in React, you need a combination of some CSS and the JS scroll event. First, assign position: sticky
to the element you need to be fixed when it's about to leave the viewport. Then, using a React ref, you access the scroll position of the scrollable div and use that logic to set your image source (you should avoid accessing the DOM directly with getElementById
in React).
Here's a working codesandbox example
Vue.js - How to change image src on scroll?
First of all, you need to listen to the scroll, then when the user scroll you check the value of the current scroll, if the value is enough for you to change the image you set in the state that you need to change the default image.
To allow the change to be dynamic you need to put a conditionnal render in your src attribute of the image with the images you want to swap.
The second condition on the handleScroll, is to re-put the default image if the user has scrolled less than 100, and only if it was not the default image
Here is the code to achieve it
<template>
<div id="app" style="height: 1800px">
<img
style="position: fixed"
alt="Vue logo"
:src="
isDefaultImage
? 'https://thumbs.dreamstime.com/b/t%C3%AAte-et-visage-de-portrait-mouette-adulte-harengs-semblant-droits-125872008.jpg'
: 'https://upload.wikimedia.org/wikipedia/commons/9/9a/Gull_portrait_ca_usa.jpg'
"
width="25%"
/>
<HelloWorld msg="Hello Vue in CodeSandbox!" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
data() {
return {
isDefaultImage: true,
};
},
created() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
handleScroll(event) {
// Any code to be executed when the window is scrolled
console.log(window.scrollY);
if (window.scrollY > 100) {
return (this.isDefaultImage = false);
}
if (window.scrollY <= 100) {
if (!this.defaultImage) {
return (this.isDefaultImage = true);
}
}
},
},
};
</script>
Link to the code sandbox : https://codesandbox.io/s/nameless-brook-q5l3g?file=/src/App.vue
How to switch image on scroll in React (like on Apple website)?
You don't need jQuery or something like this. You could subscribe to scroll
event in useEffect()
hook with addEventListener
and check scrollTop
of a scrolling container.
If you want to do the same effect as the Apple website has, you could add some magic with position: sticky
, height
in vh
units and checking window.innerHeight
.
Note that this code is simplified, not optimized, and only needed to understand the idea:
CodeSandbox
index.js
:
import { useLayoutEffect, useState } from "react";
import { render } from "react-dom";
import classnames from "classnames";
import "./index.css";
const images = [0, 1, 2, 3, 4];
const App = () => {
const [visibleImagesMap, setVisibleImagesMap] = useState(
images.reduce((map, image) => {
map[image] = false;
return map;
}, {})
);
useLayoutEffect(() => {
const handleScroll = () => {
const scrollTop = document.documentElement.scrollTop;
const viewportHeight = window.innerHeight;
const newVisibleImagesMap = images.reduce((map, image) => {
map[image] = scrollTop >= image * viewportHeight;
return map;
}, {});
setVisibleImagesMap(newVisibleImagesMap);
};
window.addEventListener("scroll", handleScroll);
handleScroll();
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<div className="app">
<div className="sticky">
<div className="frame">
{images.map((image) => (
<div
className={classnames("image", `image_${image}`, {
image_visible: visibleImagesMap[image]
})}
key={image}
/>
))}
</div>
</div>
</div>
);
};
render(<App />, document.getElementById("root"));
index.css
:
body {
margin: 0;
}
.app {
height: 500vh;
}
.sticky {
position: sticky;
top: 0;
height: 100vh;
}
.frame {
z-index: 1;
position: relative;
height: 100%;
width: 100%;
}
.image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
background-repeat: no-repeat;
background-size: cover;
}
.image_0 {
z-index: 0;
background-image: url("./images/0.jpeg");
}
.image_1 {
z-index: 1;
background-image: url("./images/1.jpeg");
}
.image_2 {
z-index: 2;
background-image: url("./images/2.jpeg");
}
.image_3 {
z-index: 3;
background-image: url("./images/3.jpeg");
}
.image_4 {
z-index: 4;
background-image: url("./images/4.jpeg");
}
.image_visible {
opacity: 1;
}
How to change a nav image once it reaches different div elements when scrolling
There are a few problems with the jQyery code you are trying to use:
1. You are only checking the scroll position on page load - you need to continuously check inside the scroll event:
$(window).on('scroll', function( /* handler function */));
2. You are trying to change the image through CSS, but the image isn't displayed using CSS. Instead you can change the src
of the img
element like this:
$(".image-test img").attr("src", imgUrl);
3. You're not checking for the bottom of the page content element (where the replacement image it to be swapped back). You can get it like this:
var contentTop = $(".page-content").offset().top;
var contentBottom = contentTop + $(".page-content").outerHeight(true);
4. You need to check if the scroll is between these positions:
if ( ($(this).scrollTop() > contentTop) && ($(this).scrollTop() < contentBottom))
For to make this responsive (i.e. so it will work if the screen size is changed after the page is loaded by resizing the window for example) you need to include it inside the scroll event handler also.
Full Code for Function
// get the URL of the image so we can use it to swap back
defaultImgUrl = $(".image-test img").attr("src");
// check the scroll position on the scroll event
$(window).on('scroll', function() {
// get the top and bottom positions pf the page content
var contentTop = $(".page-content").offset().top;
var contentBottom = contentTop + $(".page-content").outerHeight(true);
// check if the scroll position is within the page content
if (($(this).scrollTop() > contentTop) && ($(this).scrollTop() < contentBottom)) {
// change the image url
$(".image-test img").attr("src", "https://lorempixel.com/output/nature-q-c-100-50-2.jpg");
} else {
$(".image-test img").attr("src", defaultImgUrl);
}
});
Working Example:
// get the URL of the image so we can use it to swap back
defaultImgUrl = $(".image-test img").attr("src");
// check the scroll position on the scroll event
$(window).on('scroll', function() {
// get the top and bottom positions pf the page content
var contentTop = $(".page-content").offset().top;
var contentBottom = contentTop + $(".page-content").outerHeight(true);
// check if the scroll position is within the page content
if (($(this).scrollTop() > contentTop) && ($(this).scrollTop() < contentBottom)) {
// change the image url
$(".image-test img").attr("src", "https://lorempixel.com/output/nature-q-c-100-50-2.jpg");
} else {
$(".image-test img").attr("src", defaultImgUrl);
}
});
.section1,
.section2,
.page-content {
height: 100vh;
}
.section1 {
background-color: green;
padding-top: 50px;
}
.section2 {
background-color: red;
}
nav {
height: 50px;
background-color: grey;
position: fixed;
width: 100%;
display: flex;
}
.image-test img {
width: 100px;
height: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<div class="image-test">
<img src="https://lorempixel.com/output/nature-q-c-100-50-5.jpg" alt="Sample Image">
</div>
<div>
<p>Change me to a different picture once I reach the top of page content. Then change me back to the same picture as the one I had in the hero once I reach the footer.</p>
</div>
</nav>
<div class="section1" id="hero">
<h1>Hero</h1>
</div>
<div class="page-content">
<h1>Page Content</h1>
</div>
<div class="section2">
<h1>Footer</h1>
</div>
Related Topics
Invalid Attempt to Spread Non-Iterable Instance
Prevent Particular Child Element from Firing Parent'S Mouseover Event in Jquery
How to Toggle Class to a Div Element in Reactjs
Get a List of Dates Between Two Dates Using JavaScript
React-Select:Get Default Value in React-Select
Why Isnt Window.Location.Href= Not Forwarding to Page Using Safari
How to Get Pasted Value from Reactjs Onpaste Event
Javascript Date Validation ( Dd/Mm/Yyyy) & Age Checking
Javascript Generate Unique Number Based on String
404 Error When Trying to Register Serviceworker
Passing Data from Node Js to HTML Using Ejs
How to Combine Two Arrays into One Object With Key Value Pair
Json.Stringify Without Quotes on Properties
Invalid Configuration Object in Webpack
Disable Scrolling When Touch Moving Certain Element
How to Set Profile Image as First Letters of First and Last Name