Witam,
Mam problem. Potrzebuję pomocy. Muszę zsynchronizować obie animacje. Slider i animację pisania, ale nie mogę tego zrobić. Kiedy użytkownik jest na stronie (obecnej karcie otwartej w przeglądarce), działa świetnie, ale kiedy przechodzi do innej karty i wraca na stronę, coś idzie nie tak i animacja nie jest zsynchronizowana, nie wiem dlaczego. Prawdopodobnie slider próbuje nadrobić czas, w którym użytkownik był na innej karcie. Czy ktoś może mi pomóc? Wielkie dzięki!
JS:
document.addEventListener("DOMContentLoaded", function() {
const carousel = document.querySelector('.carousel');
const slides = document.querySelectorAll('.slide');
let slideWidth = slides[0].offsetWidth;
let centerOffset = (carousel.offsetWidth - slideWidth) / 2;
let currentCenterIndex = 2;
let intervalId;
const carouselPeriod = parseInt(carousel.getAttribute('data-period')) || 7600;
function updateSlideWidth() {
slideWidth = slides[0].offsetWidth;
centerOffset = (carousel.offsetWidth - slideWidth) / 2;
}
function goToSlide(index) {
const slideOffset = centerOffset - slideWidth * index;
carousel.style.transform = `translateX(${slideOffset}px)`;
currentCenterIndex = index;
slides.forEach((slide, i) => {
if (i === currentCenterIndex) {
slide.classList.add('color-slide');
} else {
slide.classList.remove('color-slide');
}
});
}
function nextSlide() {
if (currentCenterIndex < slides.length - 1) {
goToSlide(currentCenterIndex + 1);
} else {
currentCenterIndex = 0;
goToSlide(currentCenterIndex);
}
}
function startCarousel() {
intervalId = setInterval(nextSlide, carouselPeriod);
}
startCarousel();
function handleResize() {
updateSlideWidth();
goToSlide(currentCenterIndex);
}
updateSlideWidth();
window.addEventListener('resize', handleResize);
class TxtType {
constructor(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 1000;
this.txt = '';
this.totalTime = 9000;
this.timePerChar = this.totalTime / (this.toRotate.join('').length * 2);
this.isDeleting = false;
this.animationComplete = false;
this.tick();
}
tick() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';
var that = this;
var delta = this.isDeleting ? this.timePerChar / 2 : this.timePerChar;
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period - this.timePerChar * fullTxt.length;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 500;
}
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period - this.timePerChar * fullTxt.length;
this.isDeleting = true;
this.animationComplete = true;
}
setTimeout(function () {
that.tick();
}, delta);
}
}
function write() {
var elements = document.getElementsByClassName('typewrite');
for (var i = 0; i < elements.length; i++) {
var toRotate = elements[i].getAttribute('data-type');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtType(elements[i], JSON.parse(toRotate), period);
}
}
};
write();
});
CSS:
.carousel-container {
overflow: hidden;
position: relative;
}
.carousel {
display: flex;
transition: transform 0.5s ease-in-out !important;
}
.slide img {
width: 384px;
height: 305px;
filter: grayscale(1);
transition: scale 1.4s;
scale: .7;
}
.color-slide img {
filter: grayscale(0);
scale: .9;
opacity: 1;
}
.thanks_for_support {
color: #000;
text-align: center;
}
.typewrite > .wrap {
position: relative;
overflow: hidden;
}
.typewrite > .wrap::after {
content: '';
height: 100%;
width: 3px;
position: absolute;
right: -2%;
top: 0;
background-color: #000;
animation: closeBar 1.6s infinite .7s ease-out;
}
HTML:
<div class="thanks_for_support">
<h4 style="min-height: 68px;">THanks: <br/><a href=""><span class="text typewrite" data-period="7000" data-type='["TETEE", "ESTC", "TESTB", "TESTA", "WA", "DDDDDDDDD" ,"ZZZZZZ" ,"XXXXXXXXXX"]'></span></a></h4>
</div>
<div class="carousel-container">
<div class="carousel" data-period="7600">
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1531804055935-76f44d7c3621?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=688&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1508921912186-1d1a45ebb3c1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=687&q=80" alt="">
</a>
</div>
<div class="slide color-slide">
<a href="#">
<img src="https://plus.unsplash.com/premium_photo-1664457233806-e1477e52e2ab?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=765&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1554080353-a576cf803bda?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=687&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1495231916356-a86217efff12?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=736&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1566275529824-cca6d008f3da?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=687&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1457089328109-e5d9bd499191?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=663&q=80" alt="">
</a>
</div>
<div class="slide">
<a href="#">
<img src="https://images.unsplash.com/photo-1482482097755-0b595893ba63?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=688&q=80" alt="">
</a>
</div>