<!--TL08 - Модификация для Тильды. Эффект построчного появления текста https://mod.tistols.com/line-text -->
<style>
.r .split .tn-atom {
opacity: 0;
text-align: center;
color: rgb(14, 16, 15);
font-size: clamp(2rem, 5rem, 3vw);
letter-spacing: 0.05rem;
will-change: transform;
color: #0e100f;
}
.r .split * {
will-change: transform;
}
button {
display: inline-block;
outline: none;
padding: 8px 14px;
background: transparent;
border: solid 4px #0e100f;
color: #0e100f;
text-decoration: none;
border-radius: 99px;
padding: 12px 25px;
text-transform: uppercase;
font-weight: 600;
cursor: pointer;
line-height: 18px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script>
<script src="https://assets.codepen.io/16327/SplitText3-beta.min.js?b=26"></script>
<script>
gsap.registerPlugin(SplitText);
// Функция для инициализации анимации
function initSplitAnimation(element) {
gsap.set(element.querySelector(".tn-atom"), { opacity: 1 });
let split;
SplitText.create(element.querySelector(".tn-atom"), {
type: "words,lines",
linesClass: "line",
autoSplit: true,
mask: "lines",
onSplit: (self) => {
split = gsap.from(self.lines, {
duration: 1.2, // ← Увеличьте/уменьшите для изменения общей скорости (по умолчанию 0.6)
yPercent: 100,
opacity: 0,
stagger: 0.15, // ← Увеличьте/уменьшите для изменения задержки между элементами (по умолчанию 0.1)
ease: "power2.out", // ← Измените для другого эффекта ускорения/замедления
onComplete: () => {
// Дополнительные действия после завершения анимации
}
});
return split;
}
});
return split;
}
// Функция для проверки видимости элемента
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top <= (window.innerHeight || document.documentElement.clientHeight) * 0.75 &&
rect.bottom >= 0
);
}
// Обработчик скролла с Intersection Observer
document.addEventListener('DOMContentLoaded', function() {
const splitElements = document.querySelectorAll('.split');
const animatedElements = new Set();
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !animatedElements.has(entry.target)) {
animatedElements.add(entry.target);
initSplitAnimation(entry.target);
}
});
}, {
threshold: 0.5, // Срабатывает когда 50% элемента видно
rootMargin: '0px 0px -100px 0px' // Небольшой отступ снизу
});
// Наблюдаем за всеми элементами с классом split
splitElements.forEach(element => {
observer.observe(element);
});
});
</script>