| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- // 获取核心元素
- const carousel = document.getElementById('carousel');
- const track = document.getElementById('track');
- const items = document.querySelectorAll('.carousel-item-db');
- // 复制图片列表,实现无缝滚动(关键:轨道末尾拼接原列表)
- track.append(...Array.from(items).map(item => item.cloneNode(true)));
- // 重新获取包含复制项的所有图片(无缝滚动用)
- const allItems = document.querySelectorAll('.carousel-item-db');
- // 配置项:可自定义
- const config = {
- speed: 2, // 滚动速度(越大越快,建议1-5)
- centerTolerance: 50, // 居中容差(像素,越小判断越精准,建议30-80)
- itemWidth: items[0].offsetWidth + 20 // 单张图片总宽度(含间距)
- };
- let trackX = 0; // 轨道滚动的X轴偏移量
- let isHover = false; // 鼠标是否悬浮,用于暂停滚动
- // 1. 核心:更新居中激活状态(实时判断哪个图片在中央)
- function updateActiveItem() {
- // 容器的水平中心坐标(相对于视口)
- const carouselCenter = carousel.getBoundingClientRect().left + carousel.offsetWidth / 2;
- allItems.forEach(item => {
- // 每张图片的水平中心坐标(相对于视口)
- const itemCenter = item.getBoundingClientRect().left + item.offsetWidth / 2;
- // 计算图片中心与容器中心的距离
- const distance = Math.abs(itemCenter - carouselCenter);
- // 距离小于容差 → 判定为居中,添加激活样式;否则移除
- if (distance < config.centerTolerance) {
- item.classList.add('active-db');
- } else {
- item.classList.remove('active-db');
- }
- });
- }
- // 2. 无级无缝滚动核心逻辑
- function animateScroll() {
- if (isHover) return; // 鼠标悬浮则暂停滚动
- // 轨道向左偏移,实现滚动
- trackX -= config.speed;
- // 无缝滚动:当轨道滚动距离 ≥ 原列表总宽度时,重置偏移量
- if (Math.abs(trackX) >= config.itemWidth * items.length) {
- trackX = 0;
- }
- track.style.transform = `translateX(${trackX}px)`;
- // 每次滚动都更新居中激活状态
- updateActiveItem();
- // 递归执行,实现连续滚动
- requestAnimationFrame(animateScroll);
- }
- // 3. 鼠标悬浮/离开事件:暂停/恢复滚动
- carousel.addEventListener('mouseenter', () => {
- isHover = true;
- });
- carousel.addEventListener('mouseleave', () => {
- isHover = false;
- animateScroll(); // 离开后恢复滚动
- });
- // 4. 窗口大小变化时,重新计算(适配响应式)
- window.addEventListener('resize', updateActiveItem);
- // 初始化执行滚动
- animateScroll();
|