打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

微件:Banner

来自EaseCation Wiki

<style>

   #carousel- {
       position: relative;
       width: 100%;
       box-sizing: border-box;
   }
   #carousel- .carousel-track {
       display: flex;
       height: 100%;
       transition: transform 0.5s ease-in-out;
   }
   #carousel- .slide {
       flex: 0 0 100%;
       position: relative;
       height: 100%;
       overflow: hidden;
   }
   #carousel- .slide-link {
       display: block;
       width: 100%;
       height: 100%;
       text-decoration: none;
       color: inherit;
   }
   #carousel- .slide img {
       width: 100%;
       height: 100%;
       object-fit: cover;
       display: block;
   }
   #carousel- .slide-caption {
       position: absolute;
       left: 0;
       right: 0;
       bottom: 0;
       padding: 20px 30px;
       background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
       color: #fff;
       pointer-events: none;
   }
   #carousel- .slide-caption h2 {
       font-size: 24px;
       margin-bottom: 6px;
       margin-top: 0;
   }
   #carousel- .slide-caption p {
       font-size: 14px;
       margin: 0;
       opacity: 0.9;
   }
   #carousel- .carousel-btn {
       position: absolute;
       top: 50%;
       transform: translateY(-50%);
       width: 44px;
       height: 44px;
       border: none;
       border-radius: 50%;
       background: rgba(255, 255, 255, 0.7);
       color: #333;
       font-size: 22px;
       cursor: pointer;
       display: flex;
       align-items: center;
       justify-content: center;
       transition: all 0.3s;
       z-index: 10;
       user-select: none;
       padding: 0;
       line-height: 1;
   }
   #carousel- .carousel-btn:hover {
       background: rgba(255, 255, 255, 0.95);
       box-shadow: 0 2px 10px rgba(0,0,0,0.2);
   }
   #carousel- .carousel-btn.prev {
       left: 16px;
   }
   #carousel- .carousel-btn.next {
       right: 16px;
   }
   #carousel- .carousel-indicators {
       position: absolute;
       bottom: 16px;
       left: 50%;
       transform: translateX(-50%);
       display: flex;
       gap: 8px;
       z-index: 10;
   }
   #carousel- .indicator {
       width: 10px;
       height: 10px;
       border-radius: 50%;
       background: rgba(255, 255, 255, 0.6);
       cursor: pointer;
       transition: all 0.3s;
       border: none;
       padding: 0;
   }
   #carousel- .indicator.active {
       background: #fff;
       width: 24px;
       border-radius: 5px;
   }
   @media (max-width: 600px) {
       #carousel- .carousel-btn {
           width: 36px;
           height: 36px;
           font-size: 18px;
       }
       #carousel- .slide-caption h2 {
           font-size: 18px;
       }
   }

</style>

<script>

   {
       // 解析传入的 JSON 数据
       const data = JSON.parse("");
       // 获取容器内各元素
       const container = document.getElementById('carousel-');
       const track = document.getElementById('carousel-track-');
       const prevBtn = document.getElementById('carousel-prev-');
       const nextBtn = document.getElementById('carousel-next-');
       const indicatorsContainer = document.getElementById('carousel-indicators-');
       // 配置默认值
       const config = {
           slides: data.slides || [],
           autoplay: data.autoplay !== undefined ? data.autoplay : true,
           interval: data.interval || 3000,
           showArrows: data.showArrows !== undefined ? data.showArrows : true,
           showIndicators: data.showIndicators !== undefined ? data.showIndicators : true,
           showCaptions: data.showCaptions !== undefined ? data.showCaptions : true,
           width: data.width || '100%',
           height: data.height || '400px',
           objectFit: data.objectFit || 'cover',
           borderRadius: data.borderRadius || '12px',
           loop: data.loop !== undefined ? data.loop : true
       };
       // 应用样式配置
       container.style.width = config.width;
       container.style.height = config.height;
       container.style.borderRadius = config.borderRadius;
       prevBtn.style.display = config.showArrows ? 'flex' : 'none';
       nextBtn.style.display = config.showArrows ? 'flex' : 'none';
       indicatorsContainer.style.display = config.showIndicators ? 'flex' : 'none';
       const totalSlides = config.slides.length;
       if (totalSlides === 0) {

container.innerHTML = '

暂无图片

';

       } else {
           let currentIndex = 0;
           let autoPlayTimer = null;
           // 生成幻灯片 DOM
           config.slides.forEach((slide, index) => {
               const slideDiv = document.createElement('div');
               slideDiv.className = 'slide';
               const img = document.createElement('img');
               img.src = slide.image || ;
               img.alt = slide.title || '轮播图';
               img.style.objectFit = config.objectFit;
               if (slide.link) {
                   const link = document.createElement('a');
                   link.href = slide.link;
                   link.className = 'slide-link';
                   link.target = '_blank';
                   link.appendChild(img);
                   if (config.showCaptions && (slide.title || slide.description)) {
                       const caption = document.createElement('div');
                       caption.className = 'slide-caption';
                       if (slide.title) {
                           const h2 = document.createElement('h2');
                           h2.textContent = slide.title;
                           caption.appendChild(h2);
                       }
                       if (slide.description) {
                           const p = document.createElement('p');
                           p.textContent = slide.description;
                           caption.appendChild(p);
                       }
                       link.appendChild(caption);
                   }
                   slideDiv.appendChild(link);
               } else {
                   slideDiv.appendChild(img);
                   if (config.showCaptions && (slide.title || slide.description)) {
                       const caption = document.createElement('div');
                       caption.className = 'slide-caption';
                       if (slide.title) {
                           const h2 = document.createElement('h2');
                           h2.textContent = slide.title;
                           caption.appendChild(h2);
                       }
                       if (slide.description) {
                           const p = document.createElement('p');
                           p.textContent = slide.description;
                           caption.appendChild(p);
                       }
                       slideDiv.appendChild(caption);
                   }
               }
               track.appendChild(slideDiv);
           });
           // 生成指示点
           if (config.showIndicators) {
               config.slides.forEach((_, index) => {
                   const dot = document.createElement('button');
                   dot.className = 'indicator' + (index === 0 ? ' active' : );
                   dot.setAttribute('aria-label', `切换到第 ${index + 1} 张`);
                   dot.addEventListener('click', () => {
                       goToSlide(index);
                       resetAutoPlay();
                   });
                   indicatorsContainer.appendChild(dot);
               });
           }
           function goToSlide(index) {
               if (config.loop) {
                   if (index < 0) {
                       index = totalSlides - 1;
                   } else if (index >= totalSlides) {
                       index = 0;
                   }
               } else {
                   if (index < 0) index = 0;
                   if (index >= totalSlides) index = totalSlides - 1;
                   prevBtn.disabled = index === 0;
                   nextBtn.disabled = index === totalSlides - 1;
               }
               currentIndex = index;
               track.style.transform = `translateX(-${currentIndex * 100}%)`;
               const dots = indicatorsContainer.querySelectorAll('.indicator');
               dots.forEach((dot, i) => {
                   dot.classList.toggle('active', i === currentIndex);
               });
           }
           function nextSlide() {
               goToSlide(currentIndex + 1);
           }
           function prevSlide() {
               goToSlide(currentIndex - 1);
           }
           function startAutoPlay() {
               if (!config.autoplay || totalSlides <= 1) return;
               if (autoPlayTimer) clearInterval(autoPlayTimer);
               autoPlayTimer = setInterval(nextSlide, config.interval);
           }
           function stopAutoPlay() {
               if (autoPlayTimer) {
                   clearInterval(autoPlayTimer);
                   autoPlayTimer = null;
               }
           }
           function resetAutoPlay() {
               stopAutoPlay();
               startAutoPlay();
           }
           nextBtn.addEventListener('click', () => {
               nextSlide();
               resetAutoPlay();
           });
           prevBtn.addEventListener('click', () => {
               prevSlide();
               resetAutoPlay();
           });
           container.addEventListener('mouseenter', stopAutoPlay);
           container.addEventListener('mouseleave', startAutoPlay);
           document.addEventListener('keydown', (e) => {
               if (e.key === 'ArrowLeft') {
                   prevSlide();
                   resetAutoPlay();
               } else if (e.key === 'ArrowRight') {
                   nextSlide();
                   resetAutoPlay();
               }
           });
           let touchStartX = 0;
           let touchEndX = 0;
           container.addEventListener('touchstart', (e) => {
               touchStartX = e.changedTouches[0].screenX;
               stopAutoPlay();
           }, { passive: true });
           container.addEventListener('touchend', (e) => {
               touchEndX = e.changedTouches[0].screenX;
               const diff = touchStartX - touchEndX;
               if (Math.abs(diff) > 50) {
                   if (diff > 0) {
                       nextSlide();
                   } else {
                       prevSlide();
                   }
                   resetAutoPlay();
               } else {
                   startAutoPlay();
               }
           }, { passive: true });
           // 初始化
           goToSlide(0);
           if (config.loop === false) {
               prevBtn.disabled = currentIndex === 0;
           }
           startAutoPlay();
       }
   }

</script>