How to implement open curtain animation - javascript

I am trying to copy an open curtain animation like in the following where the side divs expand horizontally on the background image on scroll.
I have a working example with the following code
import { useState, useEffect, useRef, useCallback } from "react";
import "./styles.css";
export default function App() {
// check window scroll direction
const [y, setY] = useState(null);
const [scrollDirection, setScrollDirection] = useState("");
const boxTwo = useRef(null);
const boxTwoLeft = useRef(null);
const boxTwoRight = useRef(null);
const countRefTranslateX = useRef(0);
// check window scroll direction https://stackoverflow.com/questions/62497110/detect-scroll-direction-in-react-js
const handleScrollDirection = useCallback(
(e) => {
const window = e.currentTarget;
if (y > window.scrollY) {
setScrollDirection("up");
} else if (y < window.scrollY) {
setScrollDirection("down");
}
setY(window.scrollY);
},
[y]
);
const handleScroll = useCallback(() => {
if (boxTwo.current) {
let position = boxTwo.current.getBoundingClientRect();
// checking for partial visibility and if 50 pixels of the element is visible in viewport
if (
position.top + 50 < window.innerHeight &&
position.bottom >= 0 &&
scrollDirection === "down"
) {
countRefTranslateX.current = countRefTranslateX.current + 3;
boxTwoLeft.current.style.transform = `translateX(-${countRefTranslateX.current}px)`;
boxTwoRight.current.style.transform = `translateX(${countRefTranslateX.current}px)`;
} else if (
position.top + 50 < window.innerHeight &&
position.bottom >= 0 &&
scrollDirection === "up"
) {
countRefTranslateX.current = countRefTranslateX.current - 3;
boxTwoLeft.current.style.transform = `translateX(-${countRefTranslateX.current}px)`;
boxTwoRight.current.style.transform = `translateX(${countRefTranslateX.current}px)`;
} else {
countRefTranslateX.current = 0;
boxTwoLeft.current.style.transform = `translateX(-${countRefTranslateX.current}px)`;
boxTwoRight.current.style.transform = `translateX(${countRefTranslateX.current}px)`;
}
}
}, [scrollDirection]);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [handleScroll]);
useEffect(() => {
setY(window.scrollY);
window.addEventListener("scroll", handleScrollDirection);
return () => {
window.removeEventListener("scroll", handleScrollDirection);
};
}, [handleScrollDirection]);
return (
<div className="App">
<div className="boxOne"></div>
<div ref={boxTwo} className="boxTwo">
<div ref={boxTwoLeft} className="boxTwoLeft"></div>
<div ref={boxTwoRight} className="boxTwoRight"></div>
</div>
<div className="boxThree"></div>
</div>
);
}
I have two issues.
My right white div keeps going to the left while I scroll up
I cannot get a fixed vertical window breakpoint. My animation continues after the window has scrolled after the point I want to start/stop moving the divs
How can I resolve these issues?
My codesandbox

I've looked over what you've done but it's way too complicated.
All you want is to place two curtains (panels) on top of your content.
The container should have position:relative and the curtains should have position: absolute.
You then declare the scrollLimits in between which they should move. In the example below, 0 is the starting point and window.innerHeight the end point. Replace those values with whatever makes sense for your section, considering its vertical position in the page. You could use the section's current offsetTop and clientHeight to set the limits dynamically, based on current window size.
You then get the current scroll position and calculate the scroll percentage relative to the limits.
You then apply the percentage/2 + 50% to each curtain's transform: translateX() the left one with negative value, the right one with positive value.
Done.
document.addEventListener('scroll', revealSection);
/* function revealSection() {
const scrollLimits = [0, window.innerHeight];
const currentScroll = window.scrollY;
const percent = Math.min(currentScroll * 100 / (scrollLimits[1] - scrollLimits[0]), 100);
document.querySelector('.l-panel').style.transform = `translateX(-${percent/2 + 50}%)`;
document.querySelector('.r-panel').style.transform = `translateX(${percent/2 + 50}%)`;
} */
function revealSection() {
const top = document.querySelector('section').getBoundingClientRect().top;
const percent = Math.min(Math.max(0, (window.innerHeight - top) / window.innerHeight * 100), 100);
document.querySelector('.l-panel').style.transform = `translateX(-${percent/2 + 50}%)`;
document.querySelector('.r-panel').style.transform = `translateX(${percent/2 + 50}%)`;
}
body {
margin: 0;
}
section {
background-image: url('https://static.toss.im/assets/homepage/new tossim/section2_4_big.jpg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
width: 100%;
height: 100vh;
margin: 100vh 0;
position: relative;
overflow: hidden;
}
.l-panel, .r-panel{
position: absolute;
height: 100%;
width: 100%;
content: '';
top: 0;
background-color: white;
left: 0;
}
<section>
<div class="l-panel"></div>
<div class="r-panel"></div>
</section>
Note: change the CSS selectors so the styles apply to your section only.
Edit: I've come up with a more generic way to set the scroll interval, using the section's getBoundingClientRect().top and window.innerHeight. It's probably more useful, as you no longer have to worry about the section's position in page.
I've left the previous version in, for reference and/or for anyone who prefers it.

Related

On image change magnifier's image is not changing

But When i select the other picture it did not show in magnifier box, instead it show the default picture in magnifier. how i can fix that?. I want to change the image after selecting from below and magnifier should work on that image.
and magnifier position is very downside, can we also make the appropriate position
HTML
Css
.product-image {
height: 300px;
cursor: zoom-in;
}
.magnifier-container {
display: inline-block;
position: relative;
}
.magnifier {
display: none;
position: absolute;
top: 0;
left: 100%;
overflow: hidden;
height: 300px;
width: 300px;
border: 1px solid #ddd;
border-radius: 10px;
background-color: white;
}
.magnifier__img {
width: 1000px;
transform-origin: 150px 150px;
}
js
// most efficient way to add HTML, faster than innerHTML
const parseHTML = (htmlStr) => {
const range = document.createRange();
range.selectNode(document.body); // required in Safari
return range.createContextualFragment(htmlStr);
};
// pass this function any image element to add magnifying functionality
const makeImgMagnifiable = (img) => {
const magnifierFragment = parseHTML(`
<div class="magnifier-container">
<div class="magnifier">
<img class="magnifier__img" src="${img.src}"/>
</div>
</div>
`);
// This preserves the original element reference instead of cloning it.
img.parentElement.insertBefore(magnifierFragment, img);
const magnifierContainerEl = document.querySelector(".magnifier-container");
img.remove();
magnifierContainerEl.appendChild(img);
// query the DOM for the newly added elements
const magnifierEl = magnifierContainerEl.querySelector(".magnifier");
const magnifierImg = magnifierEl.querySelector(".magnifier__img");
// set up the transform object to be mutated as mouse events occur
const transform = {
translate: [0, 0],
scale: 1,
};
// shortcut function to set the transform css property
const setTransformStyle = (el, { translate, scale }) => {
const [xPercent, yRawPercent] = translate;
const yPercent = yRawPercent < 0 ? 0 : yRawPercent;
// make manual pixel adjustments to better center
// the magnified area over the cursor.
const [xOffset, yOffset] = [
`calc(-${xPercent}% + 250px)`,
`calc(-${yPercent}% + 70px)`,
];
el.style = `
transform: scale(${scale}) translate(${xOffset}, ${yOffset});
`;
};
// show magnified thumbnail on hover
img.addEventListener("mousemove", (event) => {
const [mouseX, mouseY] = [event.pageX + 40, event.pageY - 20];
const { top, left, bottom, right } = img.getBoundingClientRect();
transform.translate = [
((mouseX - left) / right) * 100,
((mouseY - top) / bottom) * 100,
];
magnifierEl.style = `
display: block;
top: ${mouseY}px;
left: ${mouseX}px;
`;
setTransformStyle(magnifierImg, transform);
});
// zoom in/out with mouse wheel
img.addEventListener("wheel", (event) => {
event.preventDefault();
const scrollingUp = event.deltaY < 0;
const { scale } = transform;
transform.scale =
scrollingUp && scale < 3
? scale + 0.1
: !scrollingUp && scale > 1
? scale - 0.1
: scale;
setTransformStyle(magnifierImg, transform);
});
// reset after mouse leaves
img.addEventListener("mouseleave", () => {
magnifierEl.style = "";
magnifierImg.style = "";
});
};
const img = document.querySelector(".product-image");
makeImgMagnifiable(img);

Can you set a max-background-size with JavaScript?

I'm using vanilla JS to increase a background-size value as the user scrolls down the page to create a parallax scroll effect. My function is below:
const heroBg = document.getElementById('hero');
window.addEventListener( 'scroll', function() {
while (heroBg.style.backgroundSize <= '100') {
heroBg.style.backgroundSize = 85 + window.pageYOffset/8 + '%';
console.log(heroBg.style.backgroundSize);
if (heroBg.style.backgroundSize === '100') {
console.log('too big');
break;
}
}
});
The trouble I'm having is that the while loop only appears to run once and the image stops growing well before the 'backgroundSize' hits 100.
You can't check for <= if using strings. Also, you can't add numbers and strings; you have to use brackets.
const heroBg = document.getElementById('hero');
window.addEventListener( 'scroll', function() {
while (parseInt(heroBg.style.backgroundSize) <= 100) {
heroBg.style.backgroundSize = (85 + window.pageYOffset/8) + '%';
console.log(heroBg.style.backgroundSize);
if (parseInt(heroBg.style.backgroundSize) == 100) {
console.log('too big');
break;
}
}
});
the background size property has units of measurement, for example, px or %, but it is also a text property, and to perform a comparison operation, you need to first get rid of the units of measurement and then convert to a number. I suggest considering another option for performing the above task
const $body = document.querySelector("body");
let viewportHeight = document.documentElement.clientHeight
const bgSize = _ => $body.style.backgroundSize = `${(document.documentElement.scrollTop + viewportHeight) / document.documentElement.offsetHeight * 100 * (viewportHeight / 100)}px`
bgSize()
window.addEventListener("resize", _ => {
viewportHeight = document.documentElement.clientHeight
bgSize()
})
document.addEventListener("scroll", _ => {
bgSize()
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 300vh;
background: radial-gradient(closest-side circle, black 0% 100%, transparent 100%);
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
}

Trying to get this smoother and more natural in behavior

My implementation,
http://kodhus.com/kodnest/land/PpNFTgp
I am curious, as I am not able for some reason to figure this out, how to get my JavaScript to make my slider behave more natural and smoother, if someone knows, how to, or can make this, feel free. I'd be happy to understand.
JavaScript:
const thumb = document.querySelector('.thumb');
const thumbIndicator = document.querySelector('.thumb .thumb-indicator');
const sliderContainer = document.querySelector('.slider-container');
const trackProgress = document.querySelector('.track-progress');
const sliderContainerStart = sliderContainer.offsetLeft;
const sliderContainerWidth = sliderContainer.offsetWidth;
var translate;
var dragging = false;
var percentage = 14;
document.addEventListener('mousedown', function(e) {
if (e.target.classList.contains('thumb-indicator')) {
dragging = true;
thumbIndicator.classList.add('focus');
}
});
document.addEventListener('mousemove', function(e) {
if (dragging) {
console.log('moving', e)
if (e.clientX < sliderContainerStart) {
translate = 0;
} else if (e.clientX > sliderContainerWidth + sliderContainerStart) {
translate = sliderContainerWidth;
} else {
translate = e.clientX - sliderContainer.offsetLeft;
}
thumb.style.transform = 'translate(-50%) translate(' + translate + 'px)';
trackProgress.style.transform = 'scaleX(' + translate / sliderContainerWidth + ')'
}
});
function setPercentage() {
thumb.style.transform = 'translate(-50%) translate(' + percentage/100 * sliderContainerWidth + 'px)';
trackProgress.style.transform = 'scaleX(' + percentage/100 + ')';
}
function init() {
setPercentage();
}
init();
document.addEventListener('mouseup', function(e) {
dragging = false;
thumbIndicator.classList.remove('focus');
});
EDIT: Is there a way to smoothly and naturally increment by one for every slow move?
Is it possible to make to behave as if, like when one clicks the progress bar so that it jumps there?
The kodhus site is very janky in my browser, so I can't tell if your code lacks responsiveness or whether it's the site itself. I feel that your code is a bit convoluted: translate and width / height are mixed unnecessarily; no need to use a dragging boolean when that information is always stored in the classlist. The following slider performs nicely, and has a few considerations I don't see in yours:
stopPropagation when clicking the .thumb element
drag stops if window loses focus
pointer-events: none; applied to every part of the slider but the .thumb element
let applySliderFeel = (slider, valueChangeCallback=()=>{}) => {
// Now `thumb`, `bar` and `slider` are the elements that concern us
let [ thumb, bar ] = [ '.thumb', '.bar' ].map(v => slider.querySelector(v));
let changed = amt => {
thumb.style.left = `${amt * 100}%`;
bar.style.width = `${amt * 100}%`;
valueChangeCallback(amt);
};
// Pressing down on `thumb` activates dragging
thumb.addEventListener('mousedown', evt => {
thumb.classList.add('active');
evt.preventDefault();
evt.stopPropagation();
});
// Releasing the mouse button (anywhere) deactivates dragging
document.addEventListener('mouseup', evt => thumb.classList.remove('active'));
// If the window loses focus dragging also stops - this can be a very
// nice quality of life improvement!
window.addEventListener('blur', evt => thumb.classList.remove('active'));
// Now we have to act when the mouse moves...
document.addEventListener('mousemove', evt => {
// If the drag isn't active do nothing!
if (!thumb.classList.contains('active')) return;
// Compute `xRelSlider`, which is the mouse position relative to the
// left side of the slider bar. Note that *client*X is compatible with
// getBounding*Client*Rect, and using these two values we can quickly
// get the relative x position.
let { width, left } = slider.getBoundingClientRect();
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Clamp `xRelSlider` between 0 and the slider's width
if (xRelSlider < 0) xRelSlider = 0;
if (xRelSlider > width) xRelSlider = width;
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
slider.addEventListener('mousedown', evt => {
let { width, left } = slider.getBoundingClientRect();
// Clicking the slider also activates a drag
thumb.classList.add('active');
// Consider mouse x, subtract left offset of slider, and subtract half
// the width of the thumb (so drags position the center of the thumb,
// not its left side):
let xRelSlider = evt.clientX - left - (thumb.getBoundingClientRect().width >> 1);
// Apply styling (using percents is more robust!)
changed(xRelSlider / width);
evt.preventDefault();
evt.stopPropagation();
});
changed(0);
};
let valElem = document.querySelector('.value');
applySliderFeel(document.querySelector('.slider'), amt => valElem.innerHTML = amt.toFixed(3));
.slider {
position: absolute;
width: 80%; height: 4px; background-color: rgba(0, 0, 0, 0.3);
left: 10%; top: 50%; margin-top: -2px;
}
.slider > .bar {
position: absolute;
left: 0; top: 0; width: 0; height: 100%;
background-color: #000;
pointer-events: none;
}
.slider > .thumb {
position: absolute;
width: 20px; height: 20px; background-color: #000; border-radius: 100%;
left: 0; top: 50%; margin-top: -10px;
}
.slider > .thumb.active {
box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.5);
}
<div class="slider">
<div class="bar"></div>
<div class="thumb"></div>
</div>
<div class="value"></div>

Weird scroll behavior when with chrome and smooth scrolling

I'm writing a virtual scrolling lib and encounter a weird problem which only appears in chrome and disable smooth scrolling in chrome flag fix it. One part of the logic is to use an invisible div to stretch the container and when scroll to top, fetch some new data then scroll back to old top. However, in chrome with smooth scrolling, it seems that changes to scrollTop will not be applied immediately so multiple data is fetched and scroll position is wrong.
I'm using chrome 84.0.4147.105-1 on Linux and have tested on Windows with same result. It may sometimes be hard to trigger, the safest way is to drag the scrollbar near top without trigger fetching and scroll up. Then you shall find console value jump from 0 to 900(scroll down) to a small number(why?) and trigger fetch again
const container = document.getElementById('container')
const scroller = document.getElementById('scroller')
let height = 0
let isFetching = false
const fetchData = h => {
if (isFetching) return
isFetching = true
setTimeout(() => {
height += h
scroller.style.height = height + 'px'
container.scrollTop += h
isFetching = false
}, 50)
}
fetchData(800)
container.addEventListener('scroll', ev => {
const top = ev.target.scrollTop
console.log(top)
if (top <= 50) {
fetchData(800)
}
})
#container {
height: 200px;
width: 500px;
background-color: blue;
overflow: auto;
}
#scroller {
width: 100%;
}
<div id="container">
<div id="scroller"></div>
</div>
A temporary (and really inelegant) fix is changing fetchData to
const fetchData = h => {
if (isFetching) return
isFetching = true
setTimeout(() => {
height += h
scroller.style.height = height + 'px'
container.scrollTop += h
isFetching = false
setTimeout(() => container.scrollTop += h, 200)
}, 50)
}
which scrolls again after a small delay

Determine how much of the viewport is covered by element (IntersectionObserver)

I'm using the IntersectionObserver to add and remove classes to elements as they enter the viewport.
Instead of saying "when X% of the element is visible - add this class" I would like to say "when X% of the element is visible or when X% of the viewport is covered by the element - add this class".
I'm assuming this isn't possible? If so I think it's a bit of a flaw with the IntersectionObserver because if you have an element that's 10 times taller than the viewport it'll never count as visible unless you set the threshold to 10% or less. And when you have variable height elements, especially in a responsive design, you'll have to set the threshold to something like 0.1% to be "sure" the element will receive the class (you can never be truly sure though).
Edit: In response to Mose's reply.
Edit2: Updated with several thresholds to force it to calculate percentOfViewport more often. Still not ideal.
var observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
var entryBCR = entry.target.getBoundingClientRect();
var percentOfViewport = ((entryBCR.width * entryBCR.height) * entry.intersectionRatio) / ((window.innerWidth * window.innerHeight) / 100);
console.log(entry.target.id + ' covers ' + percentOfViewport + '% of the viewport and is ' + (entry.intersectionRatio * 100) + '% visible');
if (entry.intersectionRatio > 0.25) {
entry.target.style.background = 'red';
}
else if (percentOfViewport > 50) {
entry.target.style.background = 'green';
}
else {
entry.target.style.background = 'lightgray';
}
});
}, {threshold: [0.025, 0.05, 0.075, 0.1, 0.25]});
document.querySelectorAll('#header, #tall-content').forEach(function (el) {
observer.observe(el);
});
#header {background: lightgray; min-height: 200px}
#tall-content {background: lightgray; min-height: 2000px}
<header id="header"><h1>Site header</h1></header>
<section id="tall-content">I'm a super tall section. Depending on your resolution the IntersectionObserver will never consider this element visible and thus the percentOfViewport isn't re-calculated.</section>
What you need to do is give each element a different threshold. If the element is shorter than the default threshold (in relation to the window) then the default threshold works fine, but if it's taller you need a unique threshold for that element.
Say you want to trigger elements that are either:
50% visible or
Covering 50% of the screen
Then you need to check:
If the element is shorter than 50% of the window you can use option 1
If the element is taller than 50% of the window you need to give it a threshold that is the windows' height divided by the height of the element multiplied by the threshold (50%):
function doTheThing (el) {
el.classList.add('in-view');
}
const threshold = 0.5;
document.querySelectorAll('section').forEach(el => {
const elHeight = el.getBoundingClientRect().height;
var th = threshold;
// The element is too tall to ever hit the threshold - change threshold
if (elHeight > (window.innerHeight * threshold)) {
th = ((window.innerHeight * threshold) / elHeight) * threshold;
}
new IntersectionObserver(iEls => iEls.forEach(iEl => doTheThing(iEl)), {threshold: th}).observe(el);
});
let optionsViewPort = {
root: document.querySelector('#viewport'), // assuming the viewport has an id "viewport"
rootMargin: '0px',
threshold: 1.0
}
let observerViewport = new IntersectionObserver(callback, optionsViewPort);
observerViewPort.observe(target);
In callback, given the size of the viewport, given the size of the element, given the % of overlapping, you can calculate the percent overlapped in viewport:
const percentViewPort = viewPortSquarePixel/100;
const percentOverlapped = (targetSquarePixel * percent ) / percentViewPort;
Example:
const target = document.querySelector('#target');
const viewport = document.querySelector('#viewport');
const optionsViewPort = {
root: viewport, // assuming the viewport has an id "viewport"
rootMargin: '0px',
threshold: 1.0
}
let callback = (entries, observer) => {
entries.forEach(entry => {
const percentViewPort = (parseInt(getComputedStyle(viewport).width) * parseInt(getComputedStyle(viewport).height))/100;
const percentOverlapped = ((parseInt(getComputedStyle(target).width) * parseInt(getComputedStyle(viewport).height)) * entry.intersectionRatio) / percentViewPort;
console.log("% viewport overlapped", percentOverlapped);
console.log("% of element in viewport", entry.intersectionRatio*100);
// Put here the code to evaluate percentOverlapped and target visibility to apply the desired class
});
};
let observerViewport = new IntersectionObserver(callback, optionsViewPort);
observerViewport.observe(target);
#viewport {
width: 900px;
height: 900px;
background: yellow;
position: relative;
}
#target {
position: absolute;
left: 860px;
width: 100px;
height: 100px;
z-index: 99;
background-color: red;
}
<div id="viewport">
<div id="target" />
</div>
Alternate math to calculate overlap area/percent of target with getBoundingClientRect()
const target = document.querySelector('#target');
const viewport = document.querySelector('#viewport');
const rect1 = viewport.getBoundingClientRect();
const rect2 = target.getBoundingClientRect();
const rect1Area = rect1.width * rect1.height;
const rect2Area = rect2.width * rect2.height;
const x_overlap = Math.max(0, Math.min(rect1.right, rect2.right) - Math.max(rect1.left, rect2.left));
const y_overlap = Math.max(0, Math.min(rect1.bottom, rect2.bottom) - Math.max(rect1.top, rect2.top));
const overlapArea = x_overlap * y_overlap;
const overlapPercentOfTarget = overlapArea/(rect2Area/100);
console.log("OVERLAP AREA", overlapArea);
console.log("TARGET VISIBILITY %", overlapPercentOfTarget);
#viewport {
width: 900px;
height: 900px;
background: yellow;
position: relative;
}
#target {
position: absolute;
left: 860px;
width: 100px;
height: 100px;
z-index: 99;
background-color: red;
}
<div id="viewport">
<div id="target" />
</div>
Here is a solution using ResizeObserver that fires the callback when the element is > ratio visible or when it fully covers the viewport.
/**
* Detect when an element is > ratio visible, or when it fully
* covers the viewport.
* Callback is called only once.
* Only works for height / y scrolling.
*/
export function onIntersection(
elem: HTMLElement,
ratio: number = 0.5,
callback: () => void
) {
// This helper is needed because IntersectionObserver doesn't have
// an easy mode for when the elem is taller than the viewport.
// It uses ResizeObserver to re-observe intersection when needed.
const maxRatio = window.innerHeight / elem.getBoundingClientRect().height;
const threshold = maxRatio < ratio ? 0.99 * maxRatio : ratio;
const intersectionObserver = new IntersectionObserver(
(entries) => {
const entry = entries[0];
if (entry.isIntersecting && entry.intersectionRatio >= threshold) {
disconnect();
callback();
}
},
{ threshold: [threshold] }
);
const resizeObserver = new ResizeObserver(() => {
const diff =
maxRatio - window.innerHeight / elem.getBoundingClientRect().height;
if (Math.abs(diff) > 0.0001) {
disconnect();
onIntersection(elem, ratio, callback);
}
});
const disconnect = () => {
intersectionObserver.disconnect();
resizeObserver.disconnect();
};
resizeObserver.observe(elem);
intersectionObserver.observe(elem);
}
Create two intersectionObservers:
Checks if 25% of the element is visible:
run25Percent() {
// if 25% of the element is visible, callback is triggered
const options = {
threshold: 0.25,
};
const changeBackground = (entries) => {
entries.forEach((entry) => {
if (
// check if entry is intersecting (moving into root),
entry.isIntersecting &&
// check if entry moving into root has a intersectionRatio of 25%
entry.intersectionRatio.toFixed(2) == 0.25
) {
// change Backgroundcolor here
}
});
};
const observer = new IntersectionObserver(
changeBackground,
options
);
document.querySelectorAll('#header, #tall-content').forEach(function
(el) {
observer.observe(el);
});
}
Checks if 50% of the screen is covered
run50Percent() {
//transforms the root into a thin line horizonatlly crossing the center of the screen
const options = {
rootMargin: "-49.9% 0px -49.9% 0px",
};
const changeBackground = (entries) => {
entries.forEach((entry) => {
//checks if element is intersecting
if (entry.isIntersecting) {
//change background color here
}
});
};
const observer = new IntersectionObserver(
changeBackground,
options
);
document.querySelectorAll('#header, #tall-content').forEach((el) =>
{
observer.observe(el);
}
}

Categories

Resources