212 lines
5.4 KiB
JavaScript
212 lines
5.4 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
||
const elements = document.querySelectorAll('.perCent2');
|
||
|
||
const animatePercentage = (element) => {
|
||
// 添加可见类,触发CSS过渡效果
|
||
element.classList.add('visible');
|
||
|
||
let current = 1;
|
||
const target = parseInt(element.getAttribute('data-target'));
|
||
|
||
// 重置为初始值
|
||
element.textContent = '1%';
|
||
|
||
const timer = setInterval(() => {
|
||
current += 1;
|
||
element.textContent = `${current}%`;
|
||
|
||
if (current >= target) {
|
||
clearInterval(timer);
|
||
}
|
||
}, 30);
|
||
};
|
||
|
||
const observer = new IntersectionObserver((entries) => {
|
||
entries.forEach(entry => {
|
||
if (entry.isIntersecting) {
|
||
animatePercentage(entry.target);
|
||
} else {
|
||
// 当元素离开视口时
|
||
entry.target.classList.remove('visible');
|
||
entry.target.textContent = '1%'; // 重置为初始值
|
||
}
|
||
});
|
||
}, {
|
||
threshold: 0.5,
|
||
rootMargin: '0px'
|
||
});
|
||
|
||
elements.forEach(element => {
|
||
// 初始状态设置
|
||
element.classList.remove('visible');
|
||
element.textContent = '1%';
|
||
observer.observe(element);
|
||
});
|
||
|
||
// ------------------------------
|
||
// 获取所需的DOM元素
|
||
const container = document.querySelector('.carousel-container');
|
||
const list = document.querySelector('.carousel-list');
|
||
const items = document.querySelectorAll('.carousel-item');
|
||
const prevBtn = document.querySelector('.carousel-arrow-left');
|
||
const nextBtn = document.querySelector('.carousel-arrow-right');
|
||
const indicators = document.querySelectorAll('.indicator');
|
||
|
||
// 如果元素不存在,直接返回
|
||
if (!container || !list || !items.length) {
|
||
console.error('轮播图元素不存在,初始化失败');
|
||
return;
|
||
}
|
||
|
||
// 克隆第一个和最后一个项目
|
||
const firstClone = items[0].cloneNode(true);
|
||
const lastClone = items[items.length - 1].cloneNode(true);
|
||
|
||
// 将克隆的元素添加到列表中
|
||
list.appendChild(firstClone);
|
||
list.insertBefore(lastClone, list.firstChild);
|
||
|
||
// 设置初始位置,因为添加了一个项目在前面,所以从1开始
|
||
let currentIndex = 1;
|
||
let interval = null;
|
||
let isTransitioning = false;
|
||
|
||
// 初始化位置
|
||
updatePosition(false);
|
||
|
||
// 更新位置的函数
|
||
function updatePosition(withTransition = true) {
|
||
// 如果需要过渡动画
|
||
if (withTransition) {
|
||
list.style.transition = 'transform 0.5s ease';
|
||
} else {
|
||
list.style.transition = 'none';
|
||
}
|
||
|
||
// 计算位置并应用变换
|
||
const position = -currentIndex * 100;
|
||
list.style.transform = `translateX(${position}%)`;
|
||
|
||
// 更新指示器状态,注意要减去1因为我们添加了克隆项目
|
||
updateIndicators();
|
||
}
|
||
|
||
// 更新指示器状态
|
||
function updateIndicators() {
|
||
// 考虑循环,将currentIndex转换回真实索引
|
||
const realIndex = currentIndex - 1;
|
||
// 使用模运算确保索引在有效范围内
|
||
const activeIndex = (realIndex + items.length) % items.length;
|
||
|
||
indicators.forEach((indicator, i) => {
|
||
indicator.classList.toggle('active', i === activeIndex);
|
||
});
|
||
}
|
||
|
||
// 自动播放函数
|
||
function startAutoPlay() {
|
||
if (interval) clearInterval(interval);
|
||
interval = setInterval(nextSlide, 3000);
|
||
}
|
||
|
||
// 暂停自动播放
|
||
function stopAutoPlay() {
|
||
clearInterval(interval);
|
||
}
|
||
|
||
// 下一张函数
|
||
function nextSlide() {
|
||
if (isTransitioning) return;
|
||
isTransitioning = true;
|
||
|
||
currentIndex++;
|
||
updatePosition();
|
||
}
|
||
|
||
// 上一张函数
|
||
function prevSlide() {
|
||
if (isTransitioning) return;
|
||
isTransitioning = true;
|
||
|
||
currentIndex--;
|
||
updatePosition();
|
||
}
|
||
|
||
// 处理过渡结束事件
|
||
list.addEventListener('transitionend', () => {
|
||
isTransitioning = false;
|
||
|
||
// 如果到达了最后一个克隆项
|
||
if (currentIndex >= items.length + 1) {
|
||
currentIndex = 1;
|
||
updatePosition(false);
|
||
}
|
||
|
||
// 如果到达了第一个克隆项
|
||
if (currentIndex <= 0) {
|
||
currentIndex = items.length;
|
||
updatePosition(false);
|
||
}
|
||
});
|
||
|
||
// // 绑定按钮事件
|
||
// prevBtn.addEventListener('click', () => {
|
||
// prevSlide();
|
||
// stopAutoPlay();
|
||
// startAutoPlay();
|
||
// });
|
||
|
||
// nextBtn.addEventListener('click', () => {
|
||
// nextSlide();
|
||
// stopAutoPlay();
|
||
// startAutoPlay();
|
||
// });
|
||
|
||
// 绑定指示器点击事件
|
||
indicators.forEach((indicator, index) => {
|
||
indicator.addEventListener('click', () => {
|
||
currentIndex = index + 1; // +1因为我们添加了克隆项目
|
||
updatePosition();
|
||
stopAutoPlay();
|
||
startAutoPlay();
|
||
});
|
||
});
|
||
|
||
// 鼠标悬停暂停
|
||
container.addEventListener('mouseenter', stopAutoPlay);
|
||
container.addEventListener('mouseleave', startAutoPlay);
|
||
|
||
// 添加触摸滑动支持
|
||
let touchStartX = 0;
|
||
let touchEndX = 0;
|
||
|
||
container.addEventListener('touchstart', (e) => {
|
||
touchStartX = e.touches[0].clientX;
|
||
stopAutoPlay();
|
||
});
|
||
|
||
container.addEventListener('touchend', (e) => {
|
||
touchEndX = e.changedTouches[0].clientX;
|
||
const difference = touchStartX - touchEndX;
|
||
|
||
if (Math.abs(difference) > 50) {
|
||
if (difference > 0) {
|
||
nextSlide();
|
||
} else {
|
||
prevSlide();
|
||
}
|
||
}
|
||
|
||
startAutoPlay();
|
||
});
|
||
|
||
// 开始自动播放
|
||
startAutoPlay();
|
||
|
||
|
||
|
||
});
|
||
|
||
|
||
|