JSFiddle - React, Tailwind, and code Playground
Intersection Observer test with animated element
by Travis Almand
HTML
<input type="range" id="horizontal" min="-350" max="350" value="0">
<div id="intersectionRect" class="hide"></div>
<div id="container">
<div id="contained"></div>
</div>
<div id="panel">
<div id="intersecting">isIntersecting: <span></span></div>
<div id="ratio">intersection ratio: <span></span></div>
<div class="buttons">
<button id="animate">animate</button>
<button id="hidden">hidden</button>
<button id="intersection">intersection</button>
<button id="absolute">absolute</button>
<button id="opacity">opacity</button>
</div>
</div>
SCSS
body {
align-items: center;
background-color: #E0E0E0;
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
justify-content: center;
}
#intersectionRect {
background-color: #307B21;
position: absolute;
z-index: 10;
&.hide {
display: none !important;
}
}
#container {
align-items: center;
background-color: #fff;
border: 3px solid rebeccapurple;
display: flex;
height: 400px;
justify-content: center;
width: 400px;
&.hidden {
overflow: hidden;
}
}
#contained {
background-color: rebeccapurple;
height: 200px;
width: 200px;
&.animate {
animation: sidetoside 5s linear infinite alternate;
}
&.absolute {
position: absolute !important;
}
&.opacity {
opacity: 0 !important;
}
}
#panel {
margin: 10px;
width: 400px;
.buttons {
margin: 10px 0;
}
}
#horizontal {
width: 400px;
}
@keyframes sidetoside {
0% {
transform: translate3d(-350px, 0, 0);
}
100% {
transform: translate3d(350px, 0, 0);
}
}
JavaScript
console.clear();
let sliderH = document.querySelector('#horizontal');
let container = document.querySelector('#container');
let contained = document.querySelector('#contained');
let isIntersecting = document.querySelector('#intersecting span');
let intersectionRatio = document.querySelector('#ratio span');
let animate = document.querySelector('#animate');
let hidden = document.querySelector('#hidden');
let intersection = document.querySelector('#intersection');
let absolute = document.querySelector('#absolute');
let opacity = document.querySelector('#opacity');
let intersectionRect = document.querySelector('#intersectionRect');
let threshold = [...Array(100).keys()].map(x => x / 100);
let options = {
root: container,
rootMargin: '0px',
threshold: threshold
}
let observer = new IntersectionObserver(callback, options);
observer.observe(contained);
sliderH.addEventListener('input', function (e) {
contained.style.transform = `translate3d(${e.target.value}px, 0, 0`;
});
animate.addEventListener('click', function () {
contained.classList.toggle('animate');
});
hidden.addEventListener('click', function () {
container.classList.toggle('hidden');
});
intersection.addEventListener('click', function () {
intersectionRect.classList.toggle('hide');
});
absolute.addEventListener('click', function () {
contained.classList.toggle('absolute');
});
opacity.addEventListener('click', function () {
contained.classList.toggle('opacity');
});
function callback (entries, observer) {
entries.forEach(entry => {
isIntersecting.innerText = entry.isIntersecting;
intersectionRatio.innerText = entry.intersectionRatio;
intersectionRect.style.display = entry.intersectionRatio > 0.99 ? 'none': 'block';
intersectionRect.style.height = entry.intersectionRect.height + 'px';
intersectionRect.style.width = entry.intersectionRect.width + 'px';
intersectionRect.style.top = entry.intersectionRect.top + 'px';
intersectionRect.style.left =...