简体   繁体   English

无限循环的轮播幻灯片

[英]Carousel slideshow with infinite loop

Update: 07/13更新:07/13

I've found a better method for working out the infinite scroll using a JS property called cloneNode and used that to prepend and append the clone slides to create the infinite effect.我找到了一种更好的方法来使用名为cloneNode的 JS 属性来计算无限滚动,并使用它来预先添加和附加克隆幻灯片以创建无限效果。

I've also learned a more efficient way of writing a lot of this code and was able to prevent the event bubbling that was occurring as a result of the transitionend , so that's fixed.我还学会了一种更有效的方法来编写大量此类代码,并且能够防止由于transitionend而发生的事件冒泡,因此已修复。

So, two issues remain:所以,还有两个问题:

I'm still having trouble mapping the dots to the slides.我仍然无法将点映射到幻灯片。 The clones seem to be throwing off the slide array and trying to set the dots using data- wasn't working for me.克隆似乎正在摆脱幻灯片阵列并尝试使用data-设置点 - 对我不起作用。

I'm using a transform to move the slides container to create the slideshow, but if I scale the window the slide container overflow becomes visible.我正在使用转换来移动幻灯片容器以创建幻灯片,但是如果我缩放窗口,幻灯片容器溢出变得可见。 Looking at www.ramtrucks.com , I noticed that while re-sizing the window the transform and width properties on the slideshow are changing dynamically.查看www.ramtrucks.com ,我注意到在重新调整窗口大小时,幻灯片上的 transform 和 width 属性正在动态变化。 I looked into resize events for JS but none of them seemed to cooperate with my code and I think that's because I'm using a flexbox.我研究了 JS 的调整大小事件,但它们似乎都没有与我的代码合作,我认为那是因为我使用的是 flexbox。 So somehow I need to resize and change flex properties at the same time (I think?).所以不知何故,我需要同时调整大小和更改 flex 属性(我认为?)。

在此处输入图像描述

Here's where I'm at:这是我所在的位置:

 // ----- 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>

Infinite JavaScript Carousel无限 JavaScript 轮播

  • Components should be reusable.组件应该是可重用的。 Don't use IDs at all.根本不要使用 ID Use Classes instead.改用类
  • To make a component responsive , the simplest is to set to the main wrapper ie: font-size: 3vmin;要使组件具有响应性,最简单的方法是设置主包装器,即: font-size: 3vmin; and define all sizes (font-size, widths, heights, positions, etc) for the descendants (children) in em units.并以em单位为后代(子代)定义所有大小(字体大小、宽度、高度、位置等)。
  • To highlight a bullet or slide as current target with JS an element by c (current) index and use someElement.classList.toggle("is-active", thisIndex === currentIndex)要使用 JS 通过c (当前)索引突出显示项目符号或幻灯片作为当前目标,并使用someElement.classList.toggle("is-active", thisIndex === currentIndex)

Let's start with a minimal bare-bone responsive CSS Carousel:让我们从一个最基本的响应式 CSS Carousel 开始:

 .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>

That's all regarding CSS.这就是关于 CSS 的全部内容。
"No navigation bullets in HTML?" “HTML 中没有导航项目符号?” -you might ask. -你可能会问。 No, since such stuff should be handled dynamically by JavaScript.不,因为这些东西应该由 JavaScript 动态处理。 Not by you.不是你。

Here's the simplified and improved JavaScript for the Carousel component:这是 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>

The active state for slides and bullet buttons is handled by fixing the current slide index using Fix negative modulo operator % .幻灯片和项目符号按钮的活动状态是通过使用Fix 负模运算符%修复当前幻灯片索引来处理的。

Thanks to the above els(".carousel").forEach(carousel);感谢上面的els(".carousel").forEach(carousel); and the use of classes — you can have indefinite carousels inside a single page - with each working independently from the other.和类的使用——你可以在一个页面内有无限的轮播——每个都独立于另一个工作。

PS: The above example does not contains your descriptions with text etc. since totally unrelated to the demo. PS:上面的示例不包含您的文字描述等,因为与演示完全无关。 You can add them back in with ease.您可以轻松地将它们重新添加。

I have corrected the code.我已经更正了代码。 It seems issue in flex property and issue while accessing node array.I have noted down all the issues.访问节点数组时似乎出现了 flex 属性和问题。我已经记下了所有问题。

  1. style apply in slideCard divs flex: 0 0 100%.样式适用于幻灯片 div flex:0 0 100%。 flex basis 100% will expand all the images to take 100% width. flex based 100% 会将所有图像扩展为 100% 宽度。 We need to reset all to 0 and make the currentSlide to take complete width when we are changing the slides with arrow .当我们使用箭头更改幻灯片时,我们需要将全部重置为 0 并使 currentSlide 具有完整的宽度。

  2. When we access nodes using getClassByName.It always return the array.当我们使用 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM