I've got a border that i would like to reveal when in the viewport and then stay as the complete line. i've used the following css. Does anyone know some lightweight JS to activate the animation?
.draw-line {
border-left:1px solid rgb(255,0,0);
animation: draw-line 5s;
Animation-fill-mode: forwards
}
@keyframes draw-line {
0% {
height:0
}
50% {
border-left:1px solid rgb(89,0,255)
}
100% {
height:100vh;
border-left:1px solid rgb(255,0,0)
}
}
CodePudding user response:
You can use the Insertion Observer API. This snippet will add the class draw-line
to all the viewport-div
s when the viewport-div
is in the viewport, and removes them when out of the viewport.
if (!!window.IntersectionObserver) {
let viewportDivs = [...document.querySelectorAll(".viewport-div")];
viewportDivs.forEach((div) => {
insertionObserverFunction(div);
});
}
function insertionObserverFunction(div) {
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.intersectionRatio != 0) {
div.classList.add('draw-line')
} else {
div.classList.remove('draw-line')
}
});
},
{ threshold: 0.51 }
);
observer.observe(div);
}
User the threshold
property to adjust when to add the class.
CodePudding user response:
const b = document.querySelector('.start-button');
const d = document.querySelector('.draw-line');
b.addEventListener('click', function() {
b.disabled = true;
d.style.animation = 'draw-line 5s';
});
d.addEventListener('animationend', function() {
d.style.animation = 'unset';
b.disabled = false;
});
body {
margin: 0;
}
.draw-line {
border-left: 10px solid rgb(255, 0, 0);
Animation-fill-mode: forwards
}
@keyframes draw-line {
0% {
height: 0
}
50% {
border-left: 10px solid rgb(89, 0, 255)
}
100% {
height: 100vh;
border-left: 10px solid rgb(255, 0, 0)
}
}
.start-button {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 1em 2em;
}
<div ></div>
<button >Start</button>
CodePudding user response:
I'm assuming you are using Vanilla JS?
Could this work?
function isInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
This function takes in a DOM element and checks if the element is visible in the viewport. It could be paired with an eventlistener for scroll, if it returns true, add .draw-line to the classlist. If it returns false, remove from classlist.
Edit:
Maybe I misunderstood what you wanted. If you want elements to play an animation just once and stay like that when scrolled into view.
Then this works
window.addEventListener('scroll', reveal);
function reveal() {
var reveals = document.querySelectorAll('.reveal');
for(const reveal of reveals) {
var revealTop = reveal.getBoundingClientRect().top;
var revealPoint = 150;
if(revealTop < viewport.height - revealPoint) {
reveal.classList.add('draw-line');
}
}
}
What you do here is add .reveal to every element that you want to animate. You dont need to define the styles for .reveal. It just works as some kind of guiding light on what elements you want to trigger.
RevealPoint represents the Y pixels from top.
When reveal comes into view, the animation class gets added to it and stays that way.