Home > front end >  How to pass setInterval() into a Javascript class method?
How to pass setInterval() into a Javascript class method?

Time:05-10

I'm trying to make a photo slide show. I'm trying to set a timer to run every 5 seconds with setInterval(), I'm practicing classes and don't know how would I incorporate it within the class.

const list = document.querySelector('.js-gallery');
const items = document.querySelectorAll('.gallery__item');
Array.from(list);

class Gallery {
  constructor(slideshow) {
    this.slideshow = slideshow;
    this.slideCount = list.length;
    this.items = items[0].getBoundingClientRect().width;
    this.currentSlide = 1;
  }

  transitionSlide() {
    if (this.currentSlide < this.slideCount) {
      list.style.transform = `translateX(-${this.currentSlide * this.items}px)`;
      this.currentSlide  = 1;
    } else {
      list.style.transform = `translateX(0)`;
      this.currentSlide = 1;
    }
  }

  // Trying to make a method with setInterval() so that the slide runs every 5 seconds.
  

}

const pics = new Gallery(list);
.title {
  width: 100%;
  text-align: center;
}

.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  padding: 0;
  transition: all 500ms ease;
}


.gallery-container {
  overflow: hidden;
  position: relative;
  width: 1000px;
  margin: 0 auto;
}

.gallery__item {
  list-style: none;
  height: 500px;
  min-width: 1000px;
  background-position: center center;
  background-size: cover;
}
<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">
  <link rel="stylesheet" href="style.css">
  <title>Document</title>
</head>
<body>
  <h1 >Gallery of Real Cool JS3 Images</h1>
  <div >
    <ul >
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=1062')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=837')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=1025')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=237')"></li>
    </ul>
  </div>
  <script src="script.js"></script>
</body>
</html>

CodePudding user response:

Here's a working snippet below. I've made it so that it transitions every 0.5 seconds just so that you can see it faster. If you want it at 5 seconds, change the interval to 5000 instead of 500.

In general, setInterval doesn't work any differently in a class than outside it. You just have to be mindful of this binding (i.e. if you did setInterval(this.transitionSlide, 5000), this wouldn't work as this would lose scope, hence the .bind(this))

Key things to note:

  1. You want to track the setInterval's return value, which is an interval ID. This will let you stop the interval from constantly happening.

  2. We now have 2 functions - startSlideshow and stopSlideshow and when you instantiate a new Gallery, you should use .startSlideshow() on the instance variable whenever you want it to start.

  3. You were using list.length for the slideCount when you needed to use items.length since that's what was tracking the individual slides.

const list = document.querySelector('.js-gallery');
const items = document.querySelectorAll('.gallery__item'); // Use this for slide count, not list
Array.from(list); // Doesn't do anything

class Gallery {
  constructor(slideshow) {
    this.slideshow = slideshow;
    this.slideCount = items.length;
    this.items = items[0].getBoundingClientRect().width;
    this.currentSlide = 1;
    this.slideTransitionInterval = null;
  }

  transitionSlide() {
    console.log('invoked');
    if (this.currentSlide < this.slideCount) {
      list.style.transform = `translateX(-${this.currentSlide * this.items}px)`;
      this.currentSlide  = 1;
    } else {
      this.stopSlideshow();
      list.style.transform = `translateX(0)`;
      this.currentSlide = 1;
    }
  }

  // Trying to make a method with setInterval() so that the slide runs every 5 seconds.
  startSlideshow() {
    this.stopSlideshow();
    this.slideTransitionInterval = setInterval(this.transitionSlide.bind(this), 500);
  }
  
  stopSlideshow() {
    if (this.slideTransitionInterval) {
      clearInterval(this.slideTransitionInterval);
    }
  }

}

const pics = new Gallery(list);
pics.startSlideshow();
.title {
  width: 100%;
  text-align: center;
}

.gallery {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  padding: 0;
  transition: all 500ms ease;
}


.gallery-container {
  overflow: hidden;
  position: relative;
  width: 1000px;
  margin: 0 auto;
}

.gallery__item {
  list-style: none;
  height: 500px;
  min-width: 1000px;
  background-position: center center;
  background-size: cover;
}
<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">
  <link rel="stylesheet" href="style.css">
  <title>Document</title>
</head>
<body>
  <h1 >Gallery of Real Cool JS3 Images</h1>
  <div >
    <ul >
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=1062')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=837')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=1025')"></li>
      <li  style="background-image: url('https://picsum.photos/1000/650/?image=237')"></li>
    </ul>
  </div>
  <script src="script.js" defer></script>
</body>
</html>

CodePudding user response:

Try something like this:

class MyClass {
    constructor() {
        this.startInterval(); // start interval in your constructor
    }
    
    startInterval() {
        const myInterval = setInterval(this.transitionSlide, 5000);
    }
    
    transitionSlide() {
        // ... logic for slideshow
        console.log("Slideshow transitioned.");
    }
}

const cls = new MyClass();
  • Related