Change Image on Scroll Position

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



Leave a reply



Submit