如何在自定义JavaScript中循环幻灯片并自动播放?

huangapple go评论54阅读模式
英文:

How to loop slides and autoplay in custom javascript?

问题

I'm a beginner in javascript. I downloaded a custom JavaScript slide from this website:

https://www.cssscript.com/swiper-thumbnail-paginator/

Slide demo here: [https://www.cssscript.com/demo/swiper-thumbnail-paginator/][2]

I've also created a demo on jsfiddle: [https://jsfiddle.net/t4c1nb3g/][3]

The file consists of 5 files, namely: index.html, style.css, debounce.js, script.js, slide.js

And it has 6 images.

Currently, there is no slide loop in the demo, I want the slide to start itself (autoplay) and repeat it again and again (looping).

How can I make it loop for the slide and start itself (autoplay)?

Below is the index.html file:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Slider</title>
  <link rel="stylesheet" href="css/style.css">
</head>

<body>
  <div class="slide-wrapper">
    <ul class="slide">
      <li><img src="https://i.stack.imgur.com/2fkLR.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/gN1Ri.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/FgqYP.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/su1na.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/vZYry.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/5dXtQ.jpg" alt=""></li>
    </ul>
  </div>
  <div class="wrap-controls">
    <div class="arrow-nav">
      <button class="prev"></button>
    </div>
    <ul class="custom-controls">
      <li><img src="https://i.stack.imgur.com/2fkLR.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/gN1Ri.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/FgqYP.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/su1na.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/vZYry.jpg" alt=""></li>
      <li><img src="https://i.stack.imgur.com/5dXtQ.jpg" alt=""></li>
    </ul>
    <div class="arrow-nav">
      <button class="next"></button>
    </div>
  </div>
  <script type="module" src="js/script.js"></script>
</body>

</html>

Below is the style.css file:

body {
  margin: 0px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

ul {
  padding: 0px;
  margin: 0px;
  list-style: none;
}

img {
  display: block;
  max-width: 100%;
}

.slide-wrapper {
  overflow: hidden;
}

.slide {
  display: flex;
}

.slide:hover {
  will-change: transform;
}

.slide li {
  flex-shrink: 0;
  max-width: 600px;
  margin: 0 20px;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0,0,0,.4);
  opacity: .8;
  transform: scale(.8);
  transition: .4s;
}

.slide li.active {
  opacity: 1;
  transform: scale(1);
}

[data-control="slide"] {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

[data-control="slide"] li a {
  display: block;
  width: 12px;
  height: 12px;
  background: #FB5;
  border-radius: 50%;
  overflow: hidden;
  text-indent: -999px;
  margin: 5px;
}

[data-control="slide"] li.active a, [data-control="slide"] li a:hover {
  background: #E54;
}

.custom-controls {
  display: flex;
  justify-content: center;
  margin-top: 40px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.custom-controls li {
  opacity: .8;
  transform: scale(.8);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
  margin: 2px;
  box-shadow: 0 2px 2px rgba(0,0,0,.5);
  transition: .3s;
  cursor: pointer;
}

.custom-controls li.active {
  opacity: 1;
  transform: scale(1);
}

.arrow-nav {
  display: flex;
  justify-content: space-around;
  margin: 20px 10px 0 10px;
}

.arrow-nav button {
  cursor: pointer;
  border: none;
  border-radius: 50%;
  color: white;
  width: 30px;
  height: 30px;
  background: #999 url('../img/arrow.svg') center center no-repeat;
  outline: none;
}

.arrow-nav button:hover {
  background: #333 url('../img/arrow.svg') center center no-repeat;
  transition: ease-in-out .3s;
}

.arrow-nav button.prev {
  transform: rotate(-180deg);
}

.wrap-controls {
  display: flex;
  justify-content: center;
  align-items: center;
}

Below is the debounce.js file:

export default function debounce(callback, delay) {
  let timer;
  return (...args) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      callback(...args);
      timer = null;
    }, delay);
  };
}

Below is the script.js file:

import SlideNav from './slide.js';

const slide = new SlideNav('.slide', '.slide-wrapper');
slide.init();
slide.addArrow('.prev', '.next');
slide.addControl('.custom-controls');

Below is the slide.js file:

import debounce from './debounce.js';

export class Slide {
  constructor(slide, wrapper) {
    this.slide = document.querySelector(slide)
    this.wrapper = document.querySelector(wrapper);
    this.dist = { finalPosition: 0, startX: 0, movement: 0 }
    this.activeClass = 'active';
    this.changeEvent = new Event('changeEvent');
  }

  transition(active) {
    this.slide.style.transition = active ? 'transform .3s' : '';
  }

  moveSlide(distX) {
    this.dist.movePosition = distX;
    this.slide.style.transform = `translate3d(${

<details>
<summary>英文:</summary>

I&#39;m a beginner in javascript. I downloaded a custom javacsript slide from this website:

[https://www.cssscript.com/swiper-thumbnail-paginator/][1]

Slide demo here: [https://www.cssscript.com/demo/swiper-thumbnail-paginator/][2]

I&#39;ve also created a demo on jsfiddle: [https://jsfiddle.net/t4c1nb3g/][3]

The file consists of 5 files, namely: index.html, style.css, debounce.js, script.js, slide.js

And it has 6 images.

Currently, there is no slide loop in the demo, I want the slide to start itself (autoplay) and repeat it again and again (looping).

How can I make it loop for the slide and start itself (autoplay)?

Below is the index.html file:

    &lt;!DOCTYPE html&gt;
    &lt;html lang=&quot;en&quot;&gt;
    
    &lt;head&gt;
      &lt;meta charset=&quot;UTF-8&quot;&gt;
      &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
      &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
      &lt;title&gt;Slider&lt;/title&gt;
      &lt;link rel=&quot;stylesheet&quot; href=&quot;css/style.css&quot;&gt;
    &lt;/head&gt;
    
    &lt;body&gt;
      &lt;div class=&quot;slide-wrapper&quot;&gt;
        &lt;ul class=&quot;slide&quot;&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/2fkLR.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/gN1Ri.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/FgqYP.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/su1na.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/vZYry.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/5dXtQ.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/div&gt;
      &lt;div class=&quot;wrap-controls&quot;&gt;
        &lt;div class=&quot;arrow-nav&quot;&gt;
          &lt;button class=&quot;prev&quot;&gt;&lt;/button&gt;
        &lt;/div&gt;
        &lt;ul class=&quot;custom-controls&quot;&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/2fkLR.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/gN1Ri.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/FgqYP.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/su1na.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/vZYry.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
          &lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/5dXtQ.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;div class=&quot;arrow-nav&quot;&gt;
          &lt;button class=&quot;next&quot;&gt;&lt;/button&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;script type=&quot;module&quot; src=&quot;js/script.js&quot;&gt;&lt;/script&gt;
    &lt;/body&gt;
    
    &lt;/html&gt;

Below is the style.css file:

    body {
      margin: 0px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
    }
    
    ul {
      padding: 0px;
      margin: 0px;
      list-style: none;
    }
    
    img {
      display: block;
      max-width: 100%;
    }
    
    .slide-wrapper {
      overflow: hidden;
    }
    
    .slide {
      display: flex;
    }
    
    .slide:hover {
      will-change: transform;
    }
    
    .slide li {
      flex-shrink: 0;
      max-width: 600px;
      margin: 0 20px;
      border-radius: 4px;
      overflow: hidden;
      box-shadow: 0 2px 4px rgba(0,0,0,.4);
      opacity: .8;
      transform: scale(.8);
      transition: .4s;
    }
    
    .slide li.active {
      opacity: 1;
      transform: scale(1);
    }
    
    [data-control=&quot;slide&quot;] {
      display: flex;
      justify-content: center;
      margin-top: 20px;
    }
    
    [data-control=&quot;slide&quot;] li a {
      display: block;
      width: 12px;
      height: 12px;
      background: #FB5;
      border-radius: 50%;
      overflow: hidden;
      text-indent: -999px;
      margin: 5px;
    }
    
    [data-control=&quot;slide&quot;] li.active a, [data-control=&quot;slide&quot;] li a:hover {
      background: #E54;
    }
    
    .custom-controls {
      display: flex;
      justify-content: center;
      margin-top: 40px;
      margin-bottom: 20px;
      flex-wrap: wrap;
    }
    
    .custom-controls li {
      opacity: .8;
      transform: scale(.8);
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;
      margin: 2px;
      box-shadow: 0 2px 2px rgba(0,0,0,.5);
      transition: .3s;
      cursor: pointer;
    }
    
    .custom-controls li.active {
      opacity: 1;
      transform: scale(1);
    }
    
    .arrow-nav {
      display: flex;
      justify-content: space-around;
      margin: 20px 10px 0 10px;
    }
    
    .arrow-nav button {
      cursor: pointer;
      border: none;
      border-radius: 50%;
      color: white;
      width: 30px;
      height: 30px;
      background: #999 url(&#39;../img/arrow.svg&#39;) center center no-repeat;
      outline: none;
    }
    
    .arrow-nav button:hover {
      background: #333 url(&#39;../img/arrow.svg&#39;) center center no-repeat;
      transition: ease-in-out .3s;
    }
    
    .arrow-nav button.prev {
      transform: rotate(-180deg);
    }
    
    .wrap-controls {
      display: flex;
      justify-content: center;
      align-items: center;
    }

Below is the debounce.js file:

    export default function debounce(callback, delay) {
      let timer;
      return (...args) =&gt; {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() =&gt; {
          callback(...args);
          timer = null;
        }, delay);
      };
    }

Below is the script.js file:

    import SlideNav from &#39;./slide.js&#39;;
    
    const slide = new SlideNav(&#39;.slide&#39;, &#39;.slide-wrapper&#39;);
    slide.init();
    slide.addArrow(&#39;.prev&#39;, &#39;.next&#39;);
    slide.addControl(&#39;.custom-controls&#39;);

Below is the slide.js file:

    import debounce from &#39;./debounce.js&#39;;
    
    export class Slide {
      constructor(slide, wrapper) {
        this.slide = document.querySelector(slide)
        this.wrapper = document.querySelector(wrapper);
        this.dist = { finalPosition: 0, startX: 0, movement: 0 }
        this.activeClass = &#39;active&#39;;
        this.changeEvent = new Event(&#39;changeEvent&#39;);
      }
    
      transition(active) {
        this.slide.style.transition = active ? &#39;transform .3s&#39; : &#39;&#39;;
      }
    
      moveSlide(distX) {
        this.dist.movePosition = distX;
        this.slide.style.transform = `translate3d(${distX}px, 0, 0)`;
      }
    
      updatePosition(clientX) {
        this.dist.movement = (this.dist.startX - clientX) * 1.6;
        return this.dist.finalPosition - this.dist.movement;
      }
    
      onStart(event) {
        let movetype;
        if (event.type === &#39;mousedown&#39;) {
          event.preventDefault();
          this.dist.startX = event.clientX;
          movetype = &#39;mousemove&#39;;
        } else {
          this.dist.startX = event.changedTouches[0].clientX;
          movetype = &#39;touchmove&#39;;
        }
        this.wrapper.addEventListener(movetype, this.onMove);
        this.transition(false);
      }
    
      onMove(event) {
        const pointerPosition = (event.type === &#39;mousemove&#39;) ? event.clientX : event.changedTouches[0].clientX;
        const finalPosition = this.updatePosition(pointerPosition);
        this.moveSlide(finalPosition);
      }
    
      onEnd(event) {
        const movetype = (event.type === &#39;mouseup&#39;) ? &#39;mousemove&#39; : &#39;touchmove&#39;;
        this.wrapper.removeEventListener(movetype, this.onMove);
        this.dist.finalPosition = this.dist.movePosition;
        this.transition(true);
        this.changeSlideOnEnd();
      }
    
      changeSlideOnEnd() {
        if (this.dist.movement &gt; 120 &amp;&amp; this.index.next !== undefined) {
          this.activeNextSlide();
        } else if (this.dist.movement &lt; -120 &amp;&amp; this.index.prev !== undefined) {
          this.activePrevSlide();
        } else {
          this.changeSlide(this.index.active);
        }
      }
    
      addSlideEvents() {
        this.wrapper.addEventListener(&#39;mousedown&#39;, this.onStart);
        this.wrapper.addEventListener(&#39;touchstart&#39;, this.onStart);
        this.wrapper.addEventListener(&#39;mouseup&#39;, this.onEnd);
        this.wrapper.addEventListener(&#39;touchend&#39;, this.onEnd);
      }
    
      // Slides config
    
      slidePosition(slide) {
        const margin = (this.wrapper.offsetWidth - slide.offsetWidth) / 2;
        return -(slide.offsetLeft - margin);
      }
    
      slidesConfig() {
        this.slideArray = [...this.slide.children].map((element) =&gt; {
          const position = this.slidePosition(element);
          return { position, element };
        });
      }
    
      slidesIndexNav(index) {
        const last = this.slideArray.length - 1;
        this.index = {
          prev: index ? index - 1 : undefined,
          active: index,
          next: index === last ? undefined : index + 1,
        }
      }
    
      changeSlide(index) {
        const activeSlide = this.slideArray[index];
        this.moveSlide(activeSlide.position);
        this.slidesIndexNav(index);
        this.dist.finalPosition = activeSlide.position;
        this.changeActiveClass();
        this.wrapper.dispatchEvent(this.changeEvent);
      }
    
      changeActiveClass() {
        this.slideArray.forEach(item =&gt; item.element.classList.remove(this.activeClass));
        this.slideArray[this.index.active].element.classList.add(this.activeClass);
      }
    
      activePrevSlide() {
        if (this.index.prev !== undefined) this.changeSlide(this.index.prev);
      }
    
      activeNextSlide() {
        if (this.index.next !== undefined) this.changeSlide(this.index.next);
      }
    
      onResize() {
        setTimeout(() =&gt; {
          this.slidesConfig();
          this.changeSlide(this.index.active);
        }, 1000);
      }
    
      addResizeEvent() {
        window.addEventListener(&#39;resize&#39;, this.onResize);
      }
    
      bindEvents() {
        this.onStart = this.onStart.bind(this);
        this.onMove = this.onMove.bind(this);
        this.onEnd = this.onEnd.bind(this);
    
        this.activePrevSlide = this.activePrevSlide.bind(this);
        this.activeNextSlide = this.activeNextSlide.bind(this);
    
        this.onResize = debounce(this.onResize.bind(this), 200);
      }
    
      init() {
        this.bindEvents();
        this.transition(true);
        this.addSlideEvents();
        this.slidesConfig();
        this.addResizeEvent();
        this.changeSlide(0);
        return this;
      }
    }
    
    export default class SlideNav extends Slide {
      constructor(slide, wrapper) {
        super(slide, wrapper);
        this.bindControlEvents();
      }
    
      addArrow(prev, next) {
        this.prevElement = document.querySelector(prev);
        this.nextElement = document.querySelector(next);
        this.addArrowEvent();
      }
    
      addArrowEvent() {
        this.prevElement.addEventListener(&#39;click&#39;, this.activePrevSlide);
        this.nextElement.addEventListener(&#39;click&#39;, this.activeNextSlide);
      }
    
      createControl() {
        const control = document.createElement(&#39;ul&#39;);
        control.dataset.control = &#39;slide&#39;;
        this.slideArray.forEach((item, index) =&gt; {
          control.innerHTML += `&lt;li&gt;&lt;a href=&quot;#slide${index + 1}&quot;&gt;${index + 1}&lt;/a&gt;&lt;/li&gt;`;
        });
        this.wrapper.appendChild(control);
        return control;
      }
    
      eventControl(item, index) {
        item.addEventListener(&#39;click&#39;, (event) =&gt; {
          event.preventDefault();
          this.changeSlide(index);
        });
        this.wrapper.addEventListener(&#39;changeEvent&#39;, this.activeControlItem);
      }
    
      activeControlItem() {
        this.controlArray.forEach(item =&gt; item.classList.remove(this.activeClass));
        this.controlArray[this.index.active].classList.add(this.activeClass);
      }
    
      addControl(customControl) {
        this.control = document.querySelector(customControl) || this.createControl();
        this.controlArray = [...this.control.children];
    
        this.activeControlItem();
        this.controlArray.forEach(this.eventControl);
      }
    
      bindControlEvents() {
        this.eventControl = this.eventControl.bind(this);
        this.activeControlItem = this.activeControlItem.bind(this);
      }
    }

Thank you very much,

best regards.

Franks.


  [1]: https://www.cssscript.com/swiper-thumbnail-paginator/
  [2]: https://www.cssscript.com/demo/swiper-thumbnail-paginator/
  [3]: https://jsfiddle.net/t4c1nb3g/

</details>


# 答案1
**得分**: 1

 [Codepen][1] 上调试您的情况后我终于弄清楚了

基本上您需要了解我所做的两个更改

1) 第一个更改是处理边缘情况

   - 当您位于 **结束** 并单击 **下一张** 应该回到 **开头**

   - 当您位于 **开头** 并单击 **上一张** 应该回到 **结束**


2) 第二个方面是使此滑块自动播放或循环播放

----------

现在是代码部分
----------------

对于第一个更改边缘情况),请在您的代码中将方法 `activePrevSlide`  `activeNextSlide` 修改为以下内容

```js
activePrevSlide() {
  if (this.index.prev !== undefined)
    this.changeSlide(this.index.prev);
  else
    this.changeSlide(this.slideArray.length - 1);
}

activeNextSlide() {
  if (this.index.next !== undefined)
    this.changeSlide(this.index.next);
  else
    this.changeSlide(0);
}

对于第二个方面,在 script.js 的末尾添加以下语句:

setInterval(slide.activeNextSlide, 3000);

它将每隔3秒自动播放一次(您可以自行更改间隔时间)。


<br>

最后,这是完整的代码,如果您想在这里运行它:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

(您的 JavaScript 代码)

<!-- end snippet -->

请参考上述代码以获取详细信息。

祝好

英文:

After debugging your case on Codepen, I finally figured it out.

Basically you need to know 2 changes that I made:

  1. The first one is handling the edge cases:

    • When you're at the end and click Next, you should go to the beginning

    • When you're at the beginning and click Previous, you should go to the end

  2. The 2nd aspect is making this slider autoplaying or looping.


Now for the code

For the 1st change (the edge cases), modify in your code the methods activePrevSlide and activeNextSlide as the following:

activePrevSlide() {
  if (this.index.prev !== undefined)
    this.changeSlide(this.index.prev);
  else
    this.changeSlide(this.slideArray.length - 1);
}

activeNextSlide() {
  if (this.index.next !== undefined)
    this.changeSlide(this.index.next);
  else
    this.changeSlide(0);
}

For the 2nd aspect, add at the end of script.js, this statement:

setInterval(slide.activeNextSlide, 3000);

It will autoplay each 3 seconds (you can change it definitely).


<br>

Finally, this is the full code, if you want to play here:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function debounce(callback, delay) {
let timer;
return (...args) =&gt; {
if (timer) clearTimeout(timer);
timer = setTimeout(() =&gt; {
callback(...args);
timer = null;
}, delay);
};
}
class Slide {
constructor(slide, wrapper) {
this.slide = document.querySelector(slide)
this.wrapper = document.querySelector(wrapper);
this.dist = { finalPosition: 0, startX: 0, movement: 0 }
this.activeClass = &#39;active&#39;;
this.changeEvent = new Event(&#39;changeEvent&#39;);
}
transition(active) {
this.slide.style.transition = active ? &#39;transform .3s&#39; : &#39;&#39;;
}
moveSlide(distX) {
this.dist.movePosition = distX;
this.slide.style.transform = `translate3d(${distX}px, 0, 0)`;
}
updatePosition(clientX) {
this.dist.movement = (this.dist.startX - clientX) * 1.6;
return this.dist.finalPosition - this.dist.movement;
}
onStart(event) {
let movetype;
if (event.type === &#39;mousedown&#39;) {
event.preventDefault();
this.dist.startX = event.clientX;
movetype = &#39;mousemove&#39;;
} else {
this.dist.startX = event.changedTouches[0].clientX;
movetype = &#39;touchmove&#39;;
}
this.wrapper.addEventListener(movetype, this.onMove);
this.transition(false);
}
onMove(event) {
const pointerPosition = (event.type === &#39;mousemove&#39;) ? event.clientX : event.changedTouches[0].clientX;
const finalPosition = this.updatePosition(pointerPosition);
this.moveSlide(finalPosition);
}
onEnd(event) {
const movetype = (event.type === &#39;mouseup&#39;) ? &#39;mousemove&#39; : &#39;touchmove&#39;;
this.wrapper.removeEventListener(movetype, this.onMove);
this.dist.finalPosition = this.dist.movePosition;
this.transition(true);
this.changeSlideOnEnd();
}
changeSlideOnEnd() {
if (this.dist.movement &gt; 120 &amp;&amp; this.index.next !== undefined) {
this.activeNextSlide();
} else if (this.dist.movement &lt; -120 &amp;&amp; this.index.prev !== undefined) {
this.activePrevSlide();
} else {
this.changeSlide(this.index.active);
}
}
addSlideEvents() {
this.wrapper.addEventListener(&#39;mousedown&#39;, this.onStart);
this.wrapper.addEventListener(&#39;touchstart&#39;, this.onStart);
this.wrapper.addEventListener(&#39;mouseup&#39;, this.onEnd);
this.wrapper.addEventListener(&#39;touchend&#39;, this.onEnd);
}
// Slides config
slidePosition(slide) {
const margin = (this.wrapper.offsetWidth - slide.offsetWidth) / 2;
return -(slide.offsetLeft - margin);
}
slidesConfig() {
this.slideArray = [...this.slide.children].map((element) =&gt; {
const position = this.slidePosition(element);
return { position, element };
});
}
slidesIndexNav(index) {
const last = this.slideArray.length - 1;
this.index = {
prev: index ? index - 1 : undefined,
active: index,
next: index === last ? undefined : index + 1,
}
}
changeSlide(index) {
const activeSlide = this.slideArray[index];
this.moveSlide(activeSlide.position);
this.slidesIndexNav(index);
this.dist.finalPosition = activeSlide.position;
this.changeActiveClass();
this.wrapper.dispatchEvent(this.changeEvent);
}
changeActiveClass() {
this.slideArray.forEach(item =&gt; item.element.classList.remove(this.activeClass));
this.slideArray[this.index.active].element.classList.add(this.activeClass);
}
activePrevSlide() {
if (this.index.prev !== undefined)
this.changeSlide(this.index.prev);
else
this.changeSlide(this.slideArray.length - 1);
}
activeNextSlide() {
if (this.index.next !== undefined)
this.changeSlide(this.index.next);
else
this.changeSlide(0);
}
onResize() {
setTimeout(() =&gt; {
this.slidesConfig();
this.changeSlide(this.index.active);
}, 1000);
}
addResizeEvent() {
window.addEventListener(&#39;resize&#39;, this.onResize);
}
bindEvents() {
this.onStart = this.onStart.bind(this);
this.onMove = this.onMove.bind(this);
this.onEnd = this.onEnd.bind(this);
this.activePrevSlide = this.activePrevSlide.bind(this);
this.activeNextSlide = this.activeNextSlide.bind(this);
this.onResize = debounce(this.onResize.bind(this), 200);
}
init() {
this.bindEvents();
this.transition(true);
this.addSlideEvents();
this.slidesConfig();
this.addResizeEvent();
this.changeSlide(0);
return this;
}
}
class SlideNav extends Slide {
constructor(slide, wrapper) {
super(slide, wrapper);
this.bindControlEvents();
}
addArrow(prev, next) {
this.prevElement = document.querySelector(prev);
this.nextElement = document.querySelector(next);
this.addArrowEvent();
}
addArrowEvent() {
this.prevElement.addEventListener(&#39;click&#39;, this.activePrevSlide);
this.nextElement.addEventListener(&#39;click&#39;, this.activeNextSlide);
}
createControl() {
const control = document.createElement(&#39;ul&#39;);
control.dataset.control = &#39;slide&#39;;
this.slideArray.forEach((item, index) =&gt; {
control.innerHTML += `&lt;li&gt;&lt;a href=&quot;#slide${index + 1}&quot;&gt;${index + 1}&lt;/a&gt;&lt;/li&gt;`;
});
this.wrapper.appendChild(control);
return control;
}
eventControl(item, index) {
item.addEventListener(&#39;click&#39;, (event) =&gt; {
event.preventDefault();
this.changeSlide(index);
});
this.wrapper.addEventListener(&#39;changeEvent&#39;, this.activeControlItem);
}
activeControlItem() {
this.controlArray.forEach(item =&gt; item.classList.remove(this.activeClass));
this.controlArray[this.index.active].classList.add(this.activeClass);
}
addControl(customControl) {
this.control = document.querySelector(customControl) || this.createControl();
this.controlArray = [...this.control.children];
this.activeControlItem();
this.controlArray.forEach(this.eventControl);
}
bindControlEvents() {
this.eventControl = this.eventControl.bind(this);
this.activeControlItem = this.activeControlItem.bind(this);
}
}
const slide = new SlideNav(&#39;.slide&#39;, &#39;.slide-wrapper&#39;);
slide.init();
slide.addArrow(&#39;.prev&#39;, &#39;.next&#39;);
slide.addControl(&#39;.custom-controls&#39;);
setInterval(slide.activeNextSlide, 3000);

<!-- language: lang-css -->

body {
margin: 0px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
ul {
padding: 0px;
margin: 0px;
list-style: none;
}
img {
display: block;
max-width: 100%;
}
.slide-wrapper {
overflow: hidden;
}
.slide {
display: flex;
}
.slide:hover {
will-change: transform;
}
.slide li {
flex-shrink: 0;
max-width: 600px;
margin: 0 20px;
border-radius: 4px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,.4);
opacity: .8;
transform: scale(.8);
transition: .4s;
}
.slide li.active {
opacity: 1;
transform: scale(1);
}
[data-control=&quot;slide&quot;] {
display: flex;
justify-content: center;
margin-top: 20px;
}
[data-control=&quot;slide&quot;] li a {
display: block;
width: 12px;
height: 12px;
background: #FB5;
border-radius: 50%;
overflow: hidden;
text-indent: -999px;
margin: 5px;
}
[data-control=&quot;slide&quot;] li.active a, [data-control=&quot;slide&quot;] li a:hover {
background: #E54;
}
.custom-controls {
display: flex;
justify-content: center;
margin-top: 40px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.custom-controls li {
opacity: .8;
transform: scale(.8);
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
margin: 2px;
box-shadow: 0 2px 2px rgba(0,0,0,.5);
transition: .3s;
cursor: pointer;
}
.custom-controls li.active {
opacity: 1;
transform: scale(1);
}
.arrow-nav {
display: flex;
justify-content: space-around;
margin: 20px 10px 0 10px;
}
.arrow-nav button {
cursor: pointer;
border: none;
border-radius: 50%;
color: white;
width: 30px;
height: 30px;
background: #999 url(&#39;../img/arrow.svg&#39;) center center no-repeat;
outline: none;
}
.arrow-nav button:hover {
background: #333 url(&#39;../img/arrow.svg&#39;) center center no-repeat;
transition: ease-in-out .3s;
}
.arrow-nav button.prev {
transform: rotate(-180deg);
}
.wrap-controls {
display: flex;
justify-content: center;
align-items: center;
}

<!-- language: lang-html -->

&lt;div class=&quot;slide-wrapper&quot;&gt;
&lt;ul class=&quot;slide&quot;&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/2fkLR.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/gN1Ri.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/FgqYP.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/su1na.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/vZYry.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/5dXtQ.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;wrap-controls&quot;&gt;
&lt;div class=&quot;arrow-nav&quot;&gt;
&lt;button class=&quot;prev&quot;&gt;&lt;/button&gt;
&lt;/div&gt;
&lt;ul class=&quot;custom-controls&quot;&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/2fkLR.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/gN1Ri.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/FgqYP.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/su1na.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/vZYry.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://i.stack.imgur.com/5dXtQ.jpg&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;arrow-nav&quot;&gt;
&lt;button class=&quot;next&quot;&gt;&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

Regards

huangapple
  • 本文由 发表于 2023年2月8日 08:40:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75380374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定