Вот чего я пытаюсь достичь:
-когда элементы становятся видимыми пользователю, для них один за другим запускается анимация вращения при прокрутке, и все 3 элемента становятся липкими (это означает, что они не исчезают, пока пользователь прокручивает вниз), пока анимация на последний закончен. -когда анимация завершена, страница возвращается к своему обычному поведению
Этот код не делает элементы липкими, когда это необходимо.
document.addEventListener('DOMContentLoaded', function() {
const elements = document.querySelectorAll('.animation');
let delay = 0;
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.animationDelay = `${delay}s`;
entry.target.style.animationPlayState = 'running';
console.info('running');
// Add sticky class when the element is in view
entry.target.classList.add('sticky');
delay += 2.5; // Increase delay for the next element
observer.unobserve(entry.target); // Stop observing once the animation is triggered
}
});
}, {
threshold: 0.5
}); // Trigger when 50% of the element is in view
elements.forEach(element => {
console.info('paused');
element.style.animationPlayState = 'paused'; // Pause animation until triggered
observer.observe(element);
// Remove sticky class after the animation ends
element.addEventListener('animationend', () => {
console.info('animationend')
element.classList.remove('sticky');
});
});
});
.content {
width: 75%;
max-width: 800px;
margin: 0 auto;
}
p,
h1 {
font-family: Arial, Helvetica, sans-serif;
}
h1 {
font-size: 3rem;
}
p {
font-size: 1.5rem;
line-height: 1.5;
}
.animation {
view-timeline: --subjectReveal block;
animation-timeline: --subjectReveal;
width: 200px;
height: 200px;
background-color: bisque;
animation-iteration-count: 1;
animation-name: mymove;
animation-duration: 3s;
position: relative;
/* Normal position */
}
.animation:nth-child(1) {
animation-delay: calc(var(--subjectReveal) * 1);
}
.animation:nth-child(2) {
animation-delay: calc(var(--subjectReveal) * 2);
}
.animation:nth-child(3) {
animation-delay: calc(var(--subjectReveal) * 3);
}
/* Define the sticky behavior */
.sticky {
position: sticky;
top: 10px;
/* Adjust top as needed */
z-index: 10;
/* Ensure it stays on top */
}
@keyframes mymove {
0% {
opacity: 1;
transform: rotate(0deg);
}
50% {
opacity: 1;
transform: rotate(90deg);
}
100% {
opacity: 1;
transform: rotate(180deg);
}
}
.as-console-wrapper { height:50px; }
Scroll this
<div style = "height:1000px; min-height: 300px; max-width: 100%; display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
<div class = "animation"></div>
<div class = "animation"></div>
<div class = "animation"></div>
</div>
🤔 А знаете ли вы, что...
С помощью JavaScript можно создавать клиентские приложения для мобильных устройств с использованием фреймворков, таких как React Native и NativeScript.
Хотите попробовать это?
Я использовал CSS animation-range-start
, он был в предоставленном вами коде..
но кажется, что поддерживать ее в Firefox и Safari сложно, поскольку это экспериментальная функция.
Я поработал над движениями, которые вам нужны, поэтому используйте те части, на которые вы можете обратиться!
Надеюсь, это поможет :)
document.addEventListener('DOMContentLoaded', function() {
const elementsContent = document.querySelector('.animation-content');
const elements = document.querySelectorAll('.animation');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
elements.forEach((element) => {
element.style.animationName = 'mymove'; // add animation to div
element.style.animationPlayState = 'running'; // Start animation
});
observer.unobserve(entry.target); // Stop observing
}
});
}, {
threshold: 0.8
}); // Trigger when 80% of the element is in view
observer.observe(elementsContent);
});
html,
body {
margin: 0;
padding: 2vw;
background: #222;
}
.animation-wrap {
height: 300vh;
background: #fff;
}
.animation-content {
display: flex;
justify-content: space-around;
align-items: center;
height: 100vh;
position: sticky;
top: 0;
}
.animation {
view-timeline: --subjectReveal block;
animation-timeline: --subjectReveal;
animation-range-start: entry 200%;
height: 0; /* ignore this, just for square */
width: 20vw; /* ignore this, just for square */
padding-bottom:20vw; /* ignore this, just for square */
background-color: bisque;
animation-iteration-count: 1;
animation-duration: 3s;
animation-fill-mode: forwards;
/*whenendanimation,holdstartstate*/
animation-play-state: paused;
/*pausedatfirst*/
position: relative;
/*Normalposition*/
}
.animation:nth-child(1) {
animation-delay: 0s;
}
.animation:nth-child(2) {
animation-delay: 1.4s;
}
.animation:nth-child(3) {
animation-delay: 2.8s;
}
@keyframes mymove {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(360deg);
}
100% {
transform: rotate(360deg);
}
}
div[class* = "other-content"] {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 3rem;
}
.other-content_01 {
height: 400px;
background: #eee;
}
.other-content_02 {
height: 1000px;
background: #ddd;
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel = "stylesheet" href = "test.css">
</head>
<body>
<div class = "other-content_01">
Scroll Page :)
</div>
<div class = "animation-wrap">
<div class = "animation-content">
<div class = "animation"></div>
<div class = "animation"></div>
<div class = "animation"></div>
</div>
</div>
<div class = "other-content_02">
Thank you!
</div>
<script src = "test.js"></script>
</body>
</html>