How to create a vertical carousel using plain JavaScript and CSS

后端 未结 1 944
伪装坚强ぢ
伪装坚强ぢ 2021-02-04 14:26

I am trying to create a vertical carousel using vanilla JavaScript and CSS. I know that jQuery has a carousel library but I want to have a go at building this from scratch using

相关标签:
1条回答
  • 2021-02-04 14:53

    An alternative to using CSS transform properties is to give the carousel absolute positioning inside a wrapper div and manipulate the carousel's top property. Then you can use any easing function you like to animate the sliding motion. In the snippet below, I use cubic easing in/out.

    A tricky thing to watch out for is the order in which you rotate the images and perform the sliding animation. When you want to show the next picture below, you have to:

    • slide the carousel up by the height of one picture frame
    • rotate the first image to the end
    • reset the carousel's vertical offset to zero

    To show the next picture above:

    • rotate the last image to the beginning
    • instantly move the carousel up by the height of one picture frame
    • slide the carousel down until its vertical offset reaches zero

    In the following snippet, you can set the width of the carousel by adjusting Carousel.width at the top of the script. (Although the image height doesn't have to be the same as the image width, I do assume that all images have the same dimensions.) You can also play around with the Carousel.numVisible and Carousel.duration parameters.

    var Carousel = {
      width: 100,     // Images are forced into a width of this many pixels.
      numVisible: 2,  // The number of images visible at once.
      duration: 600,  // Animation duration in milliseconds.
      padding: 2      // Vertical padding around each image, in pixels.
    };
    
    function rotateForward() {
      var carousel = Carousel.carousel,
          children = carousel.children,
          firstChild = children[0],
          lastChild = children[children.length - 1];
      carousel.insertBefore(lastChild, firstChild);
    }
    function rotateBackward() {
      var carousel = Carousel.carousel,
          children = carousel.children,
          firstChild = children[0],
          lastChild = children[children.length - 1];
      carousel.insertBefore(firstChild, lastChild.nextSibling);
    }
    
    function animate(begin, end, finalTask) {
      var wrapper = Carousel.wrapper,
          carousel = Carousel.carousel,
          change = end - begin,
          duration = Carousel.duration,
          startTime = Date.now();
      carousel.style.top = begin + 'px';
      var animateInterval = window.setInterval(function () {
        var t = Date.now() - startTime;
        if (t >= duration) {
          window.clearInterval(animateInterval);
          finalTask();
          return;
        }
        t /= (duration / 2);
        var top = begin + (t < 1 ? change / 2 * Math.pow(t, 3) :
                                   change / 2 * (Math.pow(t - 2, 3) + 2));
        carousel.style.top = top + 'px';
      }, 1000 / 60);
    }
    
    window.onload = function () {
      document.getElementById('spinner').style.display = 'none';
      var carousel = Carousel.carousel = document.getElementById('carousel'),
          images = carousel.getElementsByTagName('img'),
          numImages = images.length,
          imageWidth = Carousel.width,
          aspectRatio = images[0].width / images[0].height,
          imageHeight = imageWidth / aspectRatio,
          padding = Carousel.padding,
          rowHeight = Carousel.rowHeight = imageHeight + 2 * padding;
      carousel.style.width = imageWidth + 'px';
      for (var i = 0; i < numImages; ++i) {
        var image = images[i],
            frame = document.createElement('div');
        frame.className = 'pictureFrame';
        var aspectRatio = image.offsetWidth / image.offsetHeight;
        image.style.width = frame.style.width = imageWidth + 'px';
        image.style.height = imageHeight + 'px';
        image.style.paddingTop = padding + 'px';
        image.style.paddingBottom = padding + 'px';
        frame.style.height = rowHeight + 'px';
        carousel.insertBefore(frame, image);
        frame.appendChild(image);
      }
      Carousel.rowHeight = carousel.getElementsByTagName('div')[0].offsetHeight;
      carousel.style.height = Carousel.numVisible * Carousel.rowHeight + 'px';
      carousel.style.visibility = 'visible';
      var wrapper = Carousel.wrapper = document.createElement('div');
      wrapper.id = 'carouselWrapper';
      wrapper.style.width = carousel.offsetWidth + 'px';
      wrapper.style.height = carousel.offsetHeight + 'px';
      carousel.parentNode.insertBefore(wrapper, carousel);
      wrapper.appendChild(carousel);
      var prevButton = document.getElementById('prev'),
          nextButton = document.getElementById('next');
      prevButton.onclick = function () {
        prevButton.disabled = nextButton.disabled = true;
        rotateForward();
        animate(-Carousel.rowHeight, 0, function () {
          carousel.style.top = '0';
          prevButton.disabled = nextButton.disabled = false;
        });
      };
      nextButton.onclick = function () {
        prevButton.disabled = nextButton.disabled = true;
        animate(0, -Carousel.rowHeight, function () {
          rotateBackward();
          carousel.style.top = '0';
          prevButton.disabled = nextButton.disabled = false;
        });
      };
    };
    body {
      font-family: sans-serif;
    }
    .buttons {
      margin: 5px 0;
    }
    button {
      font-size: 14px;
      display: inline;
      padding: 3px 6px;
      border: 2px solid #ccc;
      background: #fff;
      border-radius: 5px;
      outline: none;
    }
    button:hover {
      border: 2px solid #888;
      background: #ffe;
      cursor: pointer;
    }
    #carouselWrapper {
      position: relative;
      overflow: hidden;
    }
    #carousel {
      position: absolute;
      visibility: hidden;
    }
    <div id="spinner"> 
      Loading...
    </div>
    
    <div id="carousel">
      <img src="http://malsup.github.io/images/beach1.jpg">
      <img src="http://malsup.github.io/images/beach2.jpg">
      <img src="http://malsup.github.io/images/beach3.jpg">
      <img src="http://malsup.github.io/images/beach4.jpg">
      <img src="http://malsup.github.io/images/beach5.jpg">
      <img src="http://malsup.github.io/images/beach9.jpg">
    </div>
    
    <div class="buttons">
      <button id="prev">&uarr; Prev</button>
      <button id="next">&darr; Next</button>
    </div>

    0 讨论(0)
提交回复
热议问题