无限循环轮播幻灯片

问题描述 投票:0回答:3

更新:07/13

我找到了一种更好的方法来使用名为

cloneNode
的 JS 属性来计算无限滚动,并使用它来添加和附加克隆幻灯片以创建无限效果。

我还学习了一种更有效的方法来编写大量此类代码,并且能够防止由于

transitionend
而发生的事件冒泡,所以这是固定的。

所以,还有两个问题:

我仍然无法将这些点映射到幻灯片上。克隆似乎抛弃了幻灯片阵列并尝试使用

data-
设置点对我来说不起作用。

我使用变换来移动幻灯片容器来创建幻灯片,但是如果我缩放窗口,幻灯片容器溢出就会变得可见。查看 www.ramtrucks.com,我注意到在调整窗口大小时,幻灯片上的变换和宽度属性正在动态变化。我研究了 JS 的调整大小事件,但它们似乎都不与我的代码配合,我认为这是因为我使用的是 Flexbox。所以不知何故我需要同时调整大小和更改弹性属性(我认为?)。

这就是我现在的位置:

// ----- slideshow declarations ----- //
const slideShowContainer = document.querySelector('.slideShow');
const slidesContainer = document.querySelector('.slidesContainer');
const rightBtn = document.querySelector('#slideRight');
const leftBtn = document.querySelector('#slideLeft');
const slideShowInterval = 10000;

let slides = document.querySelectorAll('.slideCard');
let index = 1;
let currentSlide;
let dots;

const firstClone = slides[0].cloneNode(true);
const lastClone = slides[slides.length - 1].cloneNode(true);

firstClone.id = 'firstClone'
lastClone.id = 'lastClone'

slidesContainer.append(firstClone);
slidesContainer.prepend(lastClone);

const slideWidth = slides[index].clientWidth;

slidesContainer.style.transform = `translateX(${-slideWidth * index}px)`;
// -------------------- //


// ----- clone swap ----- // 
const slideCollection = () => document.querySelectorAll('.slideCard');

slidesContainer.addEventListener('transitionend', () => {
  slides = slideCollection();
  if (slides[index].id === firstClone.id) {
    index = 1;
    slidesContainer.style.transition = 'none';
    slidesContainer.style.transform = 'translateX(' + (-slideWidth * index) + 'px)';
  }
  slides = slideCollection();
  if (slides[index].id === lastClone.id) {
    index = slides.length - 2;
    slidesContainer.style.transition = 'none';
    slidesContainer.style.transform = 'translateX(' + (-slideWidth * index) + 'px)';
  }
});
// -------------------- //


// ----- nav buttons ----- //
const moveRight = () => {
  slides = slideCollection();
  if (index >= slides.length - 1) return;
  index++;
  slidesContainer.style.transition = 'transform 0.4s ease-in-out';
  slidesContainer.style.transform = 'translateX(' + (-slideWidth * index) + 'px)';
  closeDisclosure();
}

const moveLeft = () => {
  slides = slideCollection();
  if (index <= 0) return;
  index--;
  slidesContainer.style.transition = 'transform 0.4s ease-in-out';
  slidesContainer.style.transform = 'translateX(' + (-slideWidth * index) + 'px)';
  closeDisclosure();
}

rightBtn.addEventListener('click', moveRight);
leftBtn.addEventListener('click', moveLeft);
// -------------------- //


// ----- selection dots ----- //
const selectDotsGroup = () => document.querySelector('slideNumberDots');
const slideSelect = () => document.querySelectorAll('.slideDot');

const setCurrentSlide = () => {
  slideDots = slideSelect();
  slideDots[index - 1].classList.add('selectedSlide');
};

setCurrentSlide();
// -------------------- //


// ----- slide autoplay ----- //
const autoplay = () => {
  currentSlide = setInterval(() => {
    moveRight();
    closeDisclosure();
  }, slideShowInterval);
}

slidesContainer.addEventListener('mouseenter', () => {
  clearInterval(currentSlide);
})

slidesContainer.addEventListener('mouseleave', autoplay);

autoplay();
// -------------------- //


// ----- disclosure window scripts ----- // 
// open disclosure
let discBtn = document.getElementsByClassName("disclosurePrompt");
let disc;
for (disc = 0; disc < discBtn.length - 0; disc++) {
  discBtn[disc].addEventListener("click", function() {
    this.nextElementSibling.classList.add("discVisible");
  });
}

// close disclosure
let closeBtn = document.getElementsByClassName("fa-times");
let close;
for (close = 0; close < closeBtn.length - 0; close++) {
  closeBtn[close].addEventListener("click", function() {
    var slideDiscWindow = document.querySelectorAll(".discVisible");
    [].forEach.call(slideDiscWindow, function(el) {
      el.classList.remove("discVisible");
    });
  });
}

// close disclosure on slide change
function closeDisclosure() {
  var slideDiscWindow = document.querySelectorAll(".discVisible");
  [].forEach.call(slideDiscWindow, function(el) {
    el.classList.remove("discVisible");
  });
}
// -------------------- //
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: darkgrey;
}

html {
  font-size: 16px;
}

.slideShowWrapper {
  display: flex;
  flex-direction: row;
  position: relative;
  width: 100%;
  height: 40vw;
  margin: 0;
  padding: 0;
  overflow: hidden;
}


/* begin slideshow layout */

.slideShow {
  display: flex;
  justify-content: flex-start;
  flex-direction: row;
  position: relative;
  width: 100vw;
  height: 40vw;
  margin: 0 auto;
  padding: 0;
  overflow: hidden;
}

.slidesContainer {
  display: flex;
  flex: 1 0 100%;
  flex-direction: row;
  width: 100vw;
  height: 40vw;
  margin: 0;
  padding: 0;
}

.slideCard {
  display: flex;
  flex-direction: row;
  flex: 1 0 100%;
  position: relative;
  height: 40vw;
  width: 100vw;
  min-width: 100%;
  margin: 0;
  padding: 0;
  background-color: transparent;
}

.fa-chevron-right {
  display: block;
  opacity: 0;
  font-size: 2.3vw;
  position: absolute;
  top: 50%;
  right: 0;
  color: white;
  margin: 0 5%;
  padding: 0;
  width: auto;
  height: auto;
  z-index: 1;
  background-color: transparent;
  cursor: pointer;
  transform-origin: center;
  transition: transform 0.15s linear, opacity 0.15s linear;
}

.fa-chevron-left {
  display: block;
  opacity: 0;
  font-size: 2.3vw;
  position: absolute;
  top: 50%;
  left: 0;
  color: white;
  margin: 0 5%;
  padding: 0;
  width: auto;
  height: auto;
  z-index: 1;
  background-color: transparent;
  cursor: pointer;
  transition: transform 0.15s linear, opacity 0.15s linear;
}

.fa-chevron-right:hover {
  transform: scale(1.2);
}

.fa-chevron-left:hover {
  transform: scale(1.2);
}

.slideShowWrapper:hover .fa-chevron-right {
  opacity: 1;
}

.slideShowWrapper:hover .fa-chevron-left {
  opacity: 1;
}

.slideNumberDots {
  display: flex;
  flex-direction: row;
  justify-content: center;
  bottom: 0%;
  gap: 0.8vw;
  position: absolute;
  width: 100%;
  z-index: 1;
  margin: 0 auto;
  padding: 1vw;
  background-color: transparent;
  pointer-events: none;
}

.slideDot {
  display: flex;
  height: 0.8vw;
  width: 0.8vw;
  border-radius: 50%;
  border: 0px solid rgb(27, 27, 27);
  margin: 0;
  padding: 0;
  background-color: white;
  transform-origin: center;
  transition: transform 0.2s linear, background-color 0.2s linear;
  pointer-events: all;
}

.slideDot:hover {
  background-color: #1c69d3;
  transform-origin: center;
  transform: scale(1.3);
  cursor: pointer;
}

.slideDot.selectedSlide {
  background-color: #1c69d3;
  transform: scale(1.2);
  transform-origin: center;
  transition: color, transform 0.3s linear;
  outline: 0.15vw solid black;
  border-radius: 50%;
}

.disclosurePrompt {
  display: flex;
  font-family: BMWTypeNext Latin TT, 'DDC Heading Font Face', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  position: absolute;
  color: white;
  font-size: 0.8vw;
  font-weight: 400;
  line-height: 1.25;
  width: fit-content;
  height: fit-content;
  top: 95%;
  left: 5%;
  cursor: pointer;
  z-index: 2;
  user-select: none;
  outline: 1px transparent;
  text-decoration: underline;
}

.disclosurePrompt:hover {
  color: #e4e4e4;
}

.disclosurePrompt:focus {
  color: #e4e4e4;
}

.disclosureContainer {
  visibility: hidden;
  width: 90vw;
  height: auto;
  outline: 1px solid black;
  background-color: rgba(0, 0, 0, 0.95);
  position: absolute;
  margin: 0 auto;
  bottom: 5%;
  left: 5%;
  opacity: 0;
  z-index: 10;
  transition: opacity, top, 0.3s linear;
}

.disclosureContainer.discVisible {
  visibility: visible;
  bottom: 10.5%;
  opacity: 1;
}

.disclosureText {
  font-family: BMWTypeNext Latin TT, 'DDC Heading Font Face', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  color: white;
  line-height: clamp(0.7rem, -0.6rem + 3vw, 0.9rem);
  font-size: clamp(0.5rem, -0.875rem + 3vw, 0.7rem);
  display: block;
  margin: 0 auto;
  padding: 1.5rem 0.5rem 0.5rem 0.5rem;
  text-align: justify;
}

.fa-times {
  display: block;
  color: white;
  font-size: 0.8em;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 12;
  padding: 0.5rem 0.5rem;
  transition: all 0.2s linear;
  cursor: pointer;
}

.fa-times:hover {
  color: #1c69d3;
  transition: all 0.2s linear;
}


/* end slideshow layout */


/* begin images */

.bmw2series {
  content: url("https://i.imgur.com/MABHqGy.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.bmw3series {
  content: url("https://i.imgur.com/Ggy6iNU.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.bmwX3 {
  content: url("https://i.imgur.com/ucYCFcu.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.bmwiX {
  content: url("https://i.imgur.com/bQhvuOY.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.bmw5series {
  content: url("https://i.imgur.com/sLYH9Gy.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.bmwPreOwned {
  content: url("https://i.imgur.com/kuOWIEJ.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}
<head>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer"
  />
</head>

<body>
  <!-- slideshow wrapper -->
  <div class="slideShowWrapper">
    <!-- slideshow controls -->
    <section id="controls">
      <a><i id="slideRight" class="fa fa-chevron-right" aria-label="Next Slide" data-slider-btn="next"></i></a>
      <a><i id="slideLeft" class="fa fa-chevron-left" aria-label="Previous Slide" data-slider-btn="prev"></i></a>
      <div class="slideNumberDots">
        <a class="slideDot" data-slide="0"></a>
        <a class="slideDot" data-slide="1"></a>
        <a class="slideDot" data-slide="2"></a>
        <a class="slideDot" data-slide="3"></a>
        <a class="slideDot" data-slide="4"></a>
        <a class="slideDot" data-slide="5"></a>
      </div>
    </section>
    <!-- slides container -->
    <div class="slidesContainer">
      <section class="slideCard" id="slide0" data-slide="0">
        <img class="bmw2series" alt="BMW 2 Series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through June 30, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit,
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through June 30, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
      <section class="slideCard" id="slide1" data-slide="1">
        <img class="bmw3series" alt="BMW 3 Series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through June 30, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit,
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through June 30, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
      <section class="slideCard" id="slide2" data-slide="2">
        <img class="bmwX3" alt="BMW X3" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through June 30, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit,
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through June 30, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
      <section class="slideCard" id="slide3" data-slide="3">
        <img class="bmwiX" alt="BMW iX" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through June 30, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit,
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through June 30, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
      <section class="slideCard" id="slide4" data-slide="4">
        <img class="bmw5series" alt="BMW 5 Series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through June 30, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit,
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through June 30, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
      <section class="slideCard" id="slide5" data-slide="5">
        <img class="bmwPreOwned" alt="BMW Certified Pre-Owned" />
        <img id="bmwCPOLogo" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements. Offer not valid in Puerto
            Rico. Monthly lease payments of $459 per month for 36 months is based on an adjusted capitalized cost of $36,155 (MSRP of $40,895, including destination and handling fee of $995, less $3,915 capitalized cost reduction, $0 security deposit
            and suggested dealer contribution of $825). Actual MSRP and dealer contribution may vary and could affect your monthly lease payment. Cash due at signing includes $3,915 capitalized cost reduction, $459 first month's payment, $925 acquisition
            fee and $0 security deposit. Lessee responsible for insurance during the lease term, excess wear and tear as defined in the lease contract, $0.25/mile over 30,000 miles, plus disposition fee of up to $495 (not to exceed an amount permissible
            by law) at lease end. Not all customers will qualify for security deposit waiver. Tax, title, license, registration and dealer fees are additional fees due at signing. Advertised payment does not include applicable taxes. Purchase option at
            lease end, excluding tax, title and government fees, is $23,719. Offer valid through May 15, 2022 and may be combined with other offers unless otherwise stated. Models pictured may be shown with metallic paint and/or additional accessories.
            Visit your authorized BMW Center for important details.
          </p>
        </div>
      </section>
    </div>
  </div>
  </div>
</body>

javascript html css carousel
3个回答
6
投票

无限 JavaScript 轮播

  • 组件应该是可重复使用的。 根本不要使用 ID。 使用类来代替。
  • 要使组件
  • 响应式,最简单的方法是设置为主包装器,即:font-size: 3vmin;
    并为
    em
    中的后代(子级)定义所有尺寸(字体大小、宽度、高度、位置等)单位。
  • 要突出显示项目符号或幻灯片作为
  • current 目标,使用 JS 通过 c
    (当前)
    index 定位元素并使用 someElement.classList.toggle("is-active", thisIndex === currentIndex)
    
    
让我们从最简单的

响应式CSS开始

.carousel { position: relative; overflow: hidden; } .carousel-slider { display: flex; } .carousel-slide { flex: 1 0 100%; } .carousel-slide img { display: block; width: 100%; height: 10em; object-fit: cover; } /* That's all. Other styles go here */
<div class="carousel">
  <div class="carousel-slider">
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/0bf?text=image1" alt="Image 1"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/fb0?text=image2" alt="Image 2"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/b0f?text=image3" alt="Image 3"></div>
  </div>
</div>

这就是关于 CSS 的全部内容。


“HTML 中没有导航项目符号?” - 您可能会问。不可以,因为这样的 UI 元素应该由 JavaScript 动态创建。不是手动,因为这是一项艰巨的任务。

这是 Carousel 组件的简化和改进的

JavaScript

// DOM utility functions: const el = (sel, par) => (par || document).querySelector(sel); const els = (sel, par) => (par || document).querySelectorAll(sel); const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop); // Helper functions: const mod = (n, m) => (n % m + m) % m; // Task: Carousel: const carousel = (elCarousel) => { const animation = 500; const pause = 5000; // Or use something like: const animation = Math.abs(elCarousel.dataset.carouselAnimation ?? 500); const elCarouselSlider = el(".carousel-slider", elCarousel); const elsSlides = els(".carousel-slide", elCarouselSlider); const elsBtns = []; let itv; // Autoslide interval let tot = elsSlides.length; // Total slides let c = 0; if (tot < 2) return; // Not enough slides. Do nothing. // Methods: const anim = (ms = animation) => { const cMod = mod(c, tot); // Move slider elCarouselSlider.style.transitionDuration = `${ms}ms`; elCarouselSlider.style.transform = `translateX(${(-c - 1) * 100}%)`; // Handle active classes (slide and bullet) elsSlides.forEach((elSlide, i) => elSlide.classList.toggle("is-active", cMod === i)); elsBtns.forEach((elBtn, i) => elBtn.classList.toggle("is-active", cMod === i)); }; const prev = () => { if (c <= -1) return; // prevent blanks on fast prev-click c -= 1; anim(); }; const next = () => { if (c >= tot) return; // prevent blanks on fast next-click c += 1; anim(); }; const goto = (index) => { c = index; anim(); }; const play = () => { itv = setInterval(next, pause + animation); }; const stop = () => { clearInterval(itv); }; // Buttons: const elPrev = elNew("button", { type: "button", className: "carousel-prev", innerHTML: "<span>Prev</span>", onclick: () => prev(), }); const elNext = elNew("button", { type: "button", className: "carousel-next", innerHTML: "<span>Next</span>", onclick: () => next(), }); // Navigation: const elNavigation = elNew("div", { className: "carousel-navigation", }); // Navigation bullets: for (let i = 0; i < tot; i++) { const elBtn = elNew("button", { type: "button", className: "carousel-bullet", onclick: () => goto(i) }); elsBtns.push(elBtn); } // Events: // Infinite slide effect: elCarouselSlider.addEventListener("transitionend", () => { if (c <= -1) c = tot - 1; if (c >= tot) c = 0; anim(0); // quickly switch to "c" slide (with animation duration 0) }); // Pause on pointer enter: elCarousel.addEventListener("pointerenter", () => stop()); elCarousel.addEventListener("pointerleave", () => play()); // Init: // Insert UI elements: elNavigation.append(...elsBtns); elCarousel.append(elPrev, elNext, elNavigation); // Clone first and last slides (for "infinite" slider effect) elCarouselSlider.prepend(elsSlides[tot - 1].cloneNode(true)); elCarouselSlider.append(elsSlides[0].cloneNode(true)); // Initial slide anim(); // Start autoplay play(); }; // Allows to use multiple carousels on the same page: els(".carousel").forEach(carousel);
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.carousel {
  position: relative;
  overflow: hidden;
  font-size: 2.5vmin;
}

.carousel-slider {
  display: flex;
  transition: 0.3s;
}

.carousel-slide {
  flex: 1 0 100%;
}

.carousel-slide img {
  display: block;
  width: 100%;
  height: 36em;
  object-fit: cover;
}

.carousel button {
  font-size: inherit;
}

.carousel-prev,
.carousel-next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  padding: 1em;
  border: none;
  cursor: pointer;
}

.carousel-prev {
  left: 2em;
}

.carousel-next {
  right: 2em;
}

.carousel-navigation {
  position: absolute;
  bottom: 1em;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 1em;
}

.carousel-bullet {
  width: 1em;
  height: 1em;
  border: none;
  background: #fff;
  cursor: pointer;
  border-radius: 50%;
}

.carousel-bullet.is-active {
  background: #1c69d3;
}
<div class="carousel">
  <div class="carousel-slider">
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/0bf?text=image1" alt="Image 1"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/fb0?text=image2" alt="Image 2"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/b0f?text=image3" alt="Image 3"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/0bf?text=image4" alt="Image 4"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/0fb?text=image5" alt="Image 5"></div>
    <div class="carousel-slide"><img src="https://via.placeholder.com/800x350/f0b?text=image6" alt="Image 6"></div>
  </div>
</div>

幻灯片和项目符号按钮的

active 状态是通过使用 修复负模运算符 %

固定当前幻灯片索引来处理的。

感谢上述

els(".carousel").forEach(carousel);

和类的使用——您可以在单个页面内拥有无限的轮播——每个轮播彼此独立工作。


0
投票
我已经更正了代码。这似乎是 Flex 属性的问题,以及访问节点数组时的问题。我已记下所有问题。

  1. 样式应用于slideCard div 弹性:0 0 100%。 flex basic 100% 将扩展所有图像以采用 100% 宽度。我们 需要将所有重置为0并使当前幻灯片完成 当我们用箭头更改幻灯片时的宽度。

  2. 当我们使用 getClassByName 访问节点时。它总是返回数组。

var slides = document.querySelectorAll(".slideCard"); var slideDots = document.querySelectorAll(".slideDot"); let currentSlide = 0; let currentArrow = null; let previousArrow = null; function resetDot() { for (let i = 0; i < slideDots.length; i++) { slideDots[i].classList.remove("selectedSlide"); } } function slideMovement(direction) { if (direction === "right") { for (let i = 0; i < slides.length; i++) { slides[i].style.flex = "0"; slides[i].style.transform = "translateX(-100%)"; } } else { for (let i = 0; i < slides.length; i++) { slides[i].style.flex = "0"; slides[i].style.transform = "translateX(100%)"; } } resetDot(); } const updateSlideStyle = (index) => { slides[index].style.flex = "1 1 100%"; slides[index].style.transition = "transform 0.6s linear"; if (previousArrow != currentArrow) { setTimeout(() => { slides[index].style.transform = "translateX(0px)"; previousArrow = currentArrow; }, 600); } else { slides[index].style.transform = "translateX(0px)"; } }; const slideEvent = (direction) => { const directionMovStep = direction === "right" ? 1 : -1; arrowClicked = directionMovStep; changeSlides(directionMovStep); updateSlideStyle(currentSlide); //Dots handle slideDots[currentSlide].classList.add("selectedSlide"); }; function setCurrentSlide(n) { if (n < 0) { currentSlide = slides.length - 1; } if (n >= slides.length) { currentSlide = 0; } } function changeSlides(n) { const direction = n >= 0 ? "right" : "left"; currentArrow = direction; setCurrentSlide((currentSlide += n)); slideMovement(direction); let discWindows = document.querySelectorAll(".discVisible"); [].forEach.call(discWindows, function(el) { el.classList.remove("discVisible"); }); } //open disclosure let discBtn = document.getElementsByClassName("disclosurePrompt"); let disc; for (disc = 0; disc < discBtn.length - 1; disc++) { discBtn[disc].addEventListener("click", function() { this.nextElementSibling.classList.add("discVisible"); }); } // //manually select slide let slideSelectBtn = document.getElementsByClassName("slideNumberDots"); slideSelectBtn[0].addEventListener("click", function(event) { const { target } = event; if (target) { currentSlide = target.getAttribute("data-slide") - 1; slideMovement(); updateSlideStyle(currentSlide); target.classList.add("selectedSlide"); } }); //close disclosure let closeBtn = document.getElementsByClassName("fa-times"); let close; for (close = 0; close < closeBtn.length - 1; close++) { closeBtn[close].addEventListener("click", function() { var slideDiscWindow = document.querySelectorAll(".discVisible"); [].forEach.call(slideDiscWindow, function(el) { el.classList.remove("discVisible"); }); }); } //slide controls let left = document.getElementById("slideLeft"); let right = document.getElementById("slideRight"); left.addEventListener("click", () => slideEvent("left")); right.addEventListener("click", () => slideEvent("right")); slideDots[currentSlide].classList.add("selectedSlide");
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: darkgrey;
}

html {
  font-size: 16px;
}


/* begin slideshow layout */

.slideShow {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  background-color: #414141;
  position: relative;
  width: 100%;
  height: 40vw;
  margin: 0 auto;
  padding: 0;
  /*overflow: hidden; */
  box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 1px 3px 1px;
}

.slidesContainer {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  background-color: #414141;
  position: relative;
  width: 100%;
  height: 40vw;
  margin: 0 auto;
  padding: 0;
}

.slideCard {
  display: flex;
  flex-direction: row;
  position: relative;
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0;
  background-color: transparent;
  flex: 1 0 100%;
}

.fa-chevron-right {
  display: block;
  opacity: 0;
  font-size: 2.3vw;
  position: absolute;
  top: 50%;
  right: 0;
  color: white;
  margin: 0 5%;
  padding: 0;
  width: auto;
  height: auto;
  z-index: 1;
  background-color: transparent;
  cursor: pointer;
  transform-origin: center;
  transition: transform 0.15s linear, opacity 0.15s linear;
}

.fa-chevron-left {
  display: block;
  opacity: 0;
  font-size: 2.3vw;
  position: absolute;
  top: 50%;
  left: 0;
  color: white;
  margin: 0 5%;
  padding: 0;
  width: auto;
  height: auto;
  z-index: 1;
  background-color: transparent;
  cursor: pointer;
  transition: transform 0.15s linear, opacity 0.15s linear;
}

.fa-chevron-right:hover {
  transform: scale(1.2);
}

.fa-chevron-left:hover {
  transform: scale(1.2);
}

.slideShow:hover .fa-chevron-right {
  opacity: 1;
}

.slideShow:hover .fa-chevron-left {
  opacity: 1;
}

.slideNumberDots {
  display: flex;
  flex-direction: row;
  justify-content: center;
  bottom: 0%;
  gap: 0.8vw;
  position: absolute;
  width: 100%;
  z-index: 1;
  margin: 0 auto;
  padding: 1vw;
  background-color: transparent;
  pointer-events: none;
}

.slideDot {
  display: flex;
  height: 0.8vw;
  width: 0.8vw;
  border-radius: 60%;
  border: 0px solid rgb(27, 27, 27);
  margin: 0;
  padding: 0;
  background-color: white;
  transform-origin: center;
  transition: transform 0.2s linear, background-color 0.2s linear;
  pointer-events: all;
}

.slideDot:hover {
  background-color: #1c69d3;
  transform-origin: center;
  transform: scale(1.3);
  cursor: pointer;
}

.slideDot.selectedSlide {
  background-color: #1c69d3;
  transform: scale(1.2);
  transform-origin: center;
  transition: color, transform 0.3s linear;
  outline: 0.15vw solid black;
  border-radius: 50%;
}

.disclosurePrompt {
  display: flex;
  font-family: BMWTypeNext Latin TT, Helvetica, Arial, sans-serif;
  position: absolute;
  color: white;
  font-size: 0.8vw;
  font-weight: 400;
  line-height: 1.25;
  width: fit-content;
  height: fit-content;
  top: 95%;
  left: 5%;
  cursor: pointer;
  z-index: 2;
  user-select: none;
  outline: 1px transparent;
  text-decoration: underline;
}

.disclosurePrompt:hover {
  color: #e4e4e4;
}

.disclosurePrompt:focus {
  color: #e4e4e4;
}

.disclosureContainer {
  visibility: hidden;
  width: 90vw;
  height: auto;
  outline: 1px solid black;
  background-color: rgba(0, 0, 0, 0.95);
  position: absolute;
  margin: 0 auto;
  bottom: 5%;
  left: 5%;
  opacity: 0;
  z-index: 10;
  transition: opacity, top, 0.3s linear;
}

.disclosureContainer.discVisible {
  visibility: visible;
  bottom: 10.5%;
  opacity: 1;
}

.disclosureText {
  font-family: BMWTypeNext Latin TT, Helvetica, Arial, sans-serif;
  color: white;
  line-height: clamp(0.7rem, -0.6rem + 3vw, 0.9rem);
  font-size: clamp(0.5rem, -0.875rem + 3vw, 0.7rem);
  display: block;
  margin: 0 auto;
  padding: 1.5rem 0.5rem 0.5rem 0.5rem;
  text-align: justify;
}

.fa-times {
  display: block;
  color: white;
  font-size: 0.8em;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 12;
  padding: 0.5rem 0.5rem;
  transition: all 0.2s linear;
  cursor: pointer;
}

.fa-times:hover {
  color: #1c69d3;
  transition: all 0.2s linear;
}


/* end slideshow layout */


/* begin animations */

.backInLeft {
  animation-name: backInLeft;
  animation-duration: 0.7s;
}

@keyframes backInLeft {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(0px);
  }
}

.backInRight {
  animation-name: backInRight;
  animation-duration: 0.7s;
}

@keyframes backInRight {
  0% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(0px);
  }
}


/* end animations */


/* begin images */

#bmw2series {
  content: url("https://i.imgur.com/MABHqGy.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

#bmw3series {
  content: url("https://i.imgur.com/Ggy6iNU.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

#bmwX3 {
  content: url("https://i.imgur.com/ucYCFcu.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

#bmwiX {
  content: url("https://i.imgur.com/bQhvuOY.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

#bmw5series {
  content: url("https://i.imgur.com/sLYH9Gy.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

#bmwPreOwned {
  content: url("https://i.imgur.com/kuOWIEJ.jpg");
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}
<html>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>

<body>
  <!--master container-->
  <div class="slideShow">
    <!--slideshow controls-->
    <section id="controls">
      <a><i id="slideRight" class="fa fa-chevron-right"></i></a>
      <a><i id="slideLeft" class="fa fa-chevron-left"></i></a>
      <div class="slideNumberDots">
        <a id="slideDot1" data-slide="1" class="slideDot"></a>
        <a id="slideDot2" data-slide="2" class="slideDot"></a>
        <a id="slideDot3" data-slide="3" class="slideDot"></a>
        <a id="slideDot4" data-slide="4" class="slideDot"></a>
        <a id="slideDot5" data-slide="5" class="slideDot"></a>
        <a id="slideDot6" data-slide="6" class="slideDot"></a>
      </div>
    </section>
    <!--slideshow container-->
    <div class="slidesContainer">
      <!--slide 1-->
      <div class="slideCard" id="slide1" value="2series">
        <img id="bmw2series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
      <!--slide 2-->
      <div class="slideCard" id="slide2" value="3series">
        <img id="bmw3series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
      <!--slide 3-->
      <div class="slideCard" id="slide3" value="X3">
        <img id="bmwX3" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
      <!--slide 4-->
      <div class="slideCard" id="slide4" value="iX">
        <img id="bmwiX" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
      <!--slide 5-->
      <div class="slideCard" id="slide5" value="5series">
        <img id="bmw5series" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
      <!--slide 6-->
      <div class="slideCard" id="slide6" value="preOwned1">
        <img id="bmwPreOwned" />
        <a class="disclosurePrompt" alt="Disclosure">Important Information</a>
        <div class="disclosureContainer">
          <i class="fa fa-times"></i>
          <p class="disclosureText">
            Through May 15, 2022, lease offer available on new 2022 BMW 228i xDrive Gran Coupe models from participating BMW Centers through BMW Financial Services NA, LLC, to customers who meet BMW Financial Services' credit requirements.
          </p>
        </div>
      </div>
    </div>
  </div>
</body>

</html>


0
投票

// without DRY .fa-chevron-right { display: block; opacity: 0; font-size: 2.3vw; position: absolute; top: 50%; right: 0; color: white; margin: 0 5%; padding: 0; width: auto; height: auto; z-index: 1; background-color: transparent; cursor: pointer; transform-origin: center; transition: transform 0.15s linear, opacity 0.15s linear; } .fa-chevron-left { display: block; opacity: 0; font-size: 2.3vw; position: absolute; top: 50%; left: 0; color: white; margin: 0 5%; padding: 0; width: auto; height: auto; z-index: 1; background-color: transparent; cursor: pointer; transition: transform 0.15s linear, opacity 0.15s linear; } .fa-chevron-right:hover { transform: scale(1.2); } .fa-chevron-left:hover { transform: scale(1.2); } .slideShowWrapper:hover .fa-chevron-right { opacity: 1; } .slideShowWrapper:hover .fa-chevron-left { opacity: 1; } #bmw2series { content: url("https://i.imgur.com/MABHqGy.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } #bmw3series { content: url("https://i.imgur.com/Ggy6iNU.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } #bmwX3 { content: url("https://i.imgur.com/ucYCFcu.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } #bmwiX { content: url("https://i.imgur.com/bQhvuOY.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } #bmw5series { content: url("https://i.imgur.com/sLYH9Gy.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } #bmwPreOwned { content: url("https://i.imgur.com/kuOWIEJ.jpg"); width: 100%; height: 100%; object-fit: cover; user-select: none; } // with DRY .fa-chevron { display: block; opacity: 0; font-size: 2.3vw; position: absolute; top: 50%; color: white; margin: 0 5%; padding: 0; width: auto; height: auto; z-index: 1; background-color: transparent; cursor: pointer; transition: transform 0.15s linear, opacity 0.15s linear; } .fa-chevron:hover { transform: scale(1.2); } .slideShowWrapper:hover .fa-chevron { opacity: 1; } .fa-chevron__right { right: 0; } .fa-chevron__left { left: 0; } .bmw { width: 100%; height: 100%; object-fit: cover; user-select: none; } .bmw__two-series { content: url("https://i.imgur.com/MABHqGy.jpg"); } .bmw__three-series { content: url("https://i.imgur.com/Ggy6iNU.jpg"); } .bmw__X-three { content: url("https://i.imgur.com/ucYCFcu.jpg"); } .bmw__IX { content: url("https://i.imgur.com/bQhvuOY.jpg"); } .bmw__five-series { content: url("https://i.imgur.com/sLYH9Gy.jpg"); } .bmw__pre-owned { content: url("https://i.imgur.com/kuOWIEJ.jpg"); }
 ...
 <a><i id="slideRight" class="fa fa-chevron right"></i></a>
<a><i id="slideLeft" class="fa fa-chevron left"></i></a>
 ...
 <img class="bmw bmw__two-series" alt="BMW 2 Series" />
 <!-- other images -->
 ...

© www.soinside.com 2019 - 2024. All rights reserved.