javascriptsliderslick.jsgsapreveal.js

How to create a slider with this kind of revealing animation?


I am trying to figure out how to create a slider with this revealing effect.

enter image description here


Solution

  • just an advice to you, if it is your first slider example...

    don't use gsap.(use lightweight options.)

    you can try html / css / 'vanilla js'. (pure javascript).

    look this carefully and understand basic structure.

    if you know enough html/css you can add any image/video to this. if it is came too complex and can't minimize it 'use slick.js' !

    // Start slider
    document.addEventListener('DOMContentLoaded', function() {
      const slider = new ChiefSlider('.slider', {
            loop: true
        });
    });
    
    /**
     * ChiefSlider by Itchief v2.0.0 (https://github.com/itchief/ui-components/tree/master/simple-adaptive-slider)
     * Copyright 2020 - 2021 Alexander Maltsev
     * Licensed under MIT (https://github.com/itchief/ui-components/blob/master/LICENSE)
     */
    
    (function() {
      if (typeof window.CustomEvent === 'function') return false;
      function CustomEvent(event, params) {
        params = params || {bubbles: false, cancelable: false, detail: null};
        var e = document.createEvent('CustomEvent');
        e.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
        return e;
      }
      window.CustomEvent = CustomEvent;
    })();
    
    var WRAPPER_SELECTOR = '.slider__wrapper';
    var ITEMS_SELECTOR = '.slider__items';
    var ITEM_SELECTOR = '.slider__item';
    var CONTROL_CLASS = 'slider__control';
    
    /* var ITEM_CLASS_ACTIVE = 'slider__item_active';
    var CONTROL_SELECTOR = '.slider__control';
    var CONTROL_CLASS_SHOW = 'slider__control_show';
    // индикаторы
    var INDICATOR_WRAPPER_ELEMENT = 'ol';
    var INDICATOR_WRAPPER_CLASS = 'slider__indicators';
    var INDICATOR_ITEM_ELEMENT = 'li';
    var INDICATOR_ITEM_CLASS = 'slider__indicator';
    var INDICATOR_ITEM_CLASS_ACTIVE = 'slider__indicator_active';
    // порог для переключения слайда (40%)
    var POS_THRESHOLD = 40;
    // класс для отключения transition
    var TRANSITION_NONE = 'transition-none';*/
    
    var SELECTOR_PREV = '.slider__control[data-slide="prev"]';
    var SELECTOR_NEXT = '.slider__control[data-slide="next"]';
    var SELECTOR_INDICATOR = '.slider__indicators>li';
    var SLIDER_TRANSITION_OFF = 'slider_disable-transition';
    var CLASS_CONTROL_HIDE = 'slider__control_hide';
    var CLASS_ITEM_ACTIVE = 'slider__item_active';
    var CLASS_INDICATOR_ACTIVE = 'active';
    
    function ChiefSlider(selector, config) {
      // элементы слайдера
      var $root = typeof selector === 'string' ?
        document.querySelector(selector) : selector;
      this._$root = $root;
      this._$wrapper = $root.querySelector(WRAPPER_SELECTOR);
      this._$items = $root.querySelector(ITEMS_SELECTOR);
      this._$itemList = $root.querySelectorAll(ITEM_SELECTOR);
      this._$controlPrev = $root.querySelector(SELECTOR_PREV);
      this._$controlNext = $root.querySelector(SELECTOR_NEXT);
      this._$indicatorList = $root.querySelectorAll(SELECTOR_INDICATOR);
      // экстремальные значения слайдов
      this._minOrder = 0;
      this._maxOrder = 0;
      this._$itemWithMinOrder = null;
      this._$itemWithMaxOrder = null;
      this._minTranslate = 0;
      this._maxTranslate = 0;
      // направление смены слайдов (по умолчанию)
      this._direction = 'next';
      // determines whether the position of item needs to be determined
      this._balancingItemsFlag = false;
      this._activeItems = [];
      // текущее значение трансформации
      this._transform = 0;
      // swipe параметры
      this._hasSwipeState = false;
      this.__swipeStartPos = 0;
      // slider properties
      this._transform = 0; // текущее значение трансформации
      this._intervalId = null;
      // configuration of the slider
      this._config = {
        loop: true,
        autoplay: false,
        interval: 5000,
        refresh: true,
        swipe: true,
      };
      for (var key in config) {
        if (this._config.hasOwnProperty(key)) {
          this._config[key] = config[key];
        }
      }
      // create some constants
      var $itemList = this._$itemList;
      var widthItem = $itemList[0].offsetWidth;
      var widthWrapper = this._$wrapper.offsetWidth;
      var itemsInVisibleArea = Math.round(widthWrapper / widthItem);
      // initial setting properties
      this._widthItem = widthItem;
      this._widthWrapper = widthWrapper;
      this._itemsInVisibleArea = itemsInVisibleArea;
      this._transformStep = 100 / itemsInVisibleArea;
      // initial setting order and translate items
      for (var i = 0, length = $itemList.length; i < length; i++) {
        $itemList[i].dataset.index = i;
        $itemList[i].dataset.order = i;
        $itemList[i].dataset.translate = 0;
        if (i < itemsInVisibleArea) {
          this._activeItems.push(i);
        }
      }
      if (this._config.loop) {
        // перемещаем последний слайд перед первым
        var count = $itemList.length - 1;
        var translate = -$itemList.length * 100;
        $itemList[count].dataset.order = -1;
        $itemList[count].dataset.translate = -$itemList.length * 100;
        $itemList[count].style.transform = 'translateX(' + translate + '%)';
        this.__refreshExtremeValues();
      } else {
        if (this._$controlPrev) {
          this._$controlPrev.classList.add(CLASS_CONTROL_HIDE);
        }
      }
      this._setActiveClass();
      this._addEventListener();
      this._updateIndicators();
      this._autoplay();
    }
    
    // подключения обработчиков событий для слайдера
    ChiefSlider.prototype._addEventListener = function() {
      var $root = this._$root;
      var $items = this._$items;
      var config = this._config;
      function onClick(e) {
        var $target = e.target;
        this._autoplay('stop');
        if ($target.classList.contains(CONTROL_CLASS)) {
          e.preventDefault();
          this._direction = $target.dataset.slide;
          this._move();
        } else if ($target.dataset.slideTo) {
          var index = parseInt($target.dataset.slideTo);
          this._moveTo(index);
        }
        if (this._config.loop) {
          this._autoplay();
        }
      }
      function onMouseEnter(e) {
        this._autoplay('stop');
      }
      function onMouseLeave(e) {
        this._autoplay();
      }
      function onTransitionStart() {
        if (this._balancingItemsFlag) {
          return;
        }
        this._balancingItemsFlag = true;
        window.requestAnimationFrame(this._balancingItems.bind(this));
      }
      function onTransitionEnd() {
        this._balancingItemsFlag = false;
      }
      function onResize() {
        window.requestAnimationFrame(this._refresh.bind(this));
      }
      function onSwipeStart(e) {
        this._autoplay('stop');
        var event = e.type.search('touch') === 0 ? e.touches[0] : e;
        this._swipeStartPos = event.clientX;
        this._hasSwipeState = true;
      }
      function onSwipeEnd(e) {
        if (!this._hasSwipeState) {
          return;
        }
        var event = e.type.search('touch') === 0 ? e.changedTouches[0] : e;
        var diffPos = this._swipeStartPos - event.clientX;
        if (diffPos > 50) {
          this._direction = 'next';
          this._move();
        } else if (diffPos < -50) {
          this._direction = 'prev';
          this._move();
        }
        this._hasSwipeState = false;
        if (this._config.loop) {
          this._autoplay();
        }
      }
      function onDragStart(e) {
        e.preventDefault();
      }
      function onVisibilityChange() {
        if (document.visibilityState === 'hidden') {
          this._autoplay('stop');
        } else if (document.visibilityState === 'visible') {
          if (this._config.loop) {
            this._autoplay();
          }
        }
      }
    
      $root.addEventListener('click', onClick.bind(this));
      $root.addEventListener('mouseenter', onMouseEnter.bind(this));
      $root.addEventListener('mouseleave', onMouseLeave.bind(this));
      // on resize
      if (config.refresh) {
        window.addEventListener('resize', onResize.bind(this));
      }
      // on transitionstart and transitionend
      if (config.loop) {
        $items.addEventListener('transition-start', onTransitionStart.bind(this));
        $items.addEventListener('transitionend', onTransitionEnd.bind(this));
      }
      // on touchstart and touchend
      if (config.swipe) {
        $root.addEventListener('touchstart', onSwipeStart.bind(this));
        $root.addEventListener('mousedown', onSwipeStart.bind(this));
        document.addEventListener('touchend', onSwipeEnd.bind(this));
        document.addEventListener('mouseup', onSwipeEnd.bind(this));
      }
      $root.addEventListener('dragstart', onDragStart.bind(this));
      // при изменении активности вкладки
      document.addEventListener('visibilitychange', onVisibilityChange.bind(this));
    };
    
    // update values of extreme properties
    ChiefSlider.prototype.__refreshExtremeValues = function() {
      var $itemList = this._$itemList;
      this._minOrder = +$itemList[0].dataset.order;
      this._maxOrder = this._minOrder;
      this._$itemByMinOrder = $itemList[0];
      this._$itemByMaxOrder = $itemList[0];
      this._minTranslate = +$itemList[0].dataset.translate;
      this._maxTranslate = this._minTranslate;
      for (var i = 0, length = $itemList.length; i < length; i++) {
        var $item = $itemList[i];
        var order = +$item.dataset.order;
        if (order < this._minOrder) {
          this._minOrder = order;
          this._$itemByMinOrder = $item;
          this._minTranslate = +$item.dataset.translate;
        } else if (order > this._maxOrder) {
          this._maxOrder = order;
          this._$itemByMaxOrder = $item;
          this._maxTranslate = +$item.dataset.translate;
        }
      }
    };
    
    // update position of item
    ChiefSlider.prototype._balancingItems = function() {
      if (!this._balancingItemsFlag) {
        return;
      }
      var $wrapper = this._$wrapper;
      var $wrapperClientRect = $wrapper.getBoundingClientRect();
      var widthHalfItem = $wrapperClientRect.width / this._itemsInVisibleArea / 2;
      var count = this._$itemList.length;
      var translate;
      var clientRect;
      if (this._direction === 'next') {
        var wrapperLeft = $wrapperClientRect.left;
        var $min = this._$itemByMinOrder;
        translate = this._minTranslate;
        clientRect = $min.getBoundingClientRect();
        if (clientRect.right < wrapperLeft - widthHalfItem) {
          $min.dataset.order = this._minOrder + count;
          translate += count * 100;
          $min.dataset.translate = translate;
          $min.style.transform = 'translateX('.concat(translate, '%)');
          // update values of extreme properties
          this.__refreshExtremeValues();
        }
      } else {
        var wrapperRight = $wrapperClientRect.right;
        var $max = this._$itemByMaxOrder;
        translate = this._maxTranslate;
        clientRect = $max.getBoundingClientRect();
        if (clientRect.left > wrapperRight + widthHalfItem) {
          $max.dataset.order = this._maxOrder - count;
          translate -= count * 100;
          $max.dataset.translate = translate;
          $max.style.transform = 'translateX('.concat(translate, '%)');
          // update values of extreme properties
          this.__refreshExtremeValues();
        }
      }
      // updating...
      requestAnimationFrame(this._balancingItems.bind(this));
    };
    
    // _setActiveClass
    ChiefSlider.prototype._setActiveClass = function() {
      var activeItems = this._activeItems;
      var $itemList = this._$itemList;
      for (var i = 0, length = $itemList.length; i < length; i++) {
        var $item = $itemList[i];
        var index = +$item.dataset.index;
        if (activeItems.indexOf(index) > -1) {
          $item.classList.add(CLASS_ITEM_ACTIVE);
        } else {
          $item.classList.remove(CLASS_ITEM_ACTIVE);
        }
      }
    };
    
    // _updateIndicators
    ChiefSlider.prototype._updateIndicators = function() {
      var $indicatorList = this._$indicatorList;
      var $itemList = this._$itemList;
      if (!$indicatorList.length) {
        return;
      }
      for (var index = 0, length = $itemList.length; index < length; index++) {
        var $item = $itemList[index];
        if ($item.classList.contains(CLASS_ITEM_ACTIVE)) {
          $indicatorList[index].classList.add(CLASS_INDICATOR_ACTIVE);
        } else {
          $indicatorList[index].classList.remove(CLASS_INDICATOR_ACTIVE);
        }
      }
    };
    
    // move slides
    ChiefSlider.prototype._move = function() {
      var step = this._direction ===
       'next' ? -this._transformStep : this._transformStep;
      var transform = this._transform + step;
      if (!this._config.loop) {
        var endTransformValue =
          this._transformStep * (this._$itemList.length - this._itemsInVisibleArea);
        transform = Math.round(transform * 10) / 10;
        if (transform < -endTransformValue || transform > 0) {
          return;
        }
        this._$controlPrev.classList.remove(CLASS_CONTROL_HIDE);
        this._$controlNext.classList.remove(CLASS_CONTROL_HIDE);
        if (transform === -endTransformValue) {
          this._$controlNext.classList.add(CLASS_CONTROL_HIDE);
        } else if (transform === 0) {
          this._$controlPrev.classList.add(CLASS_CONTROL_HIDE);
        }
      }
      var activeIndex = [];
      var i = 0;
      var length;
      var index;
      var newIndex;
      if (this._direction === 'next') {
        for (i = 0, length = this._activeItems.length; i < length; i++) {
          index = this._activeItems[i];
          newIndex = ++index;
          if (newIndex > this._$itemList.length - 1) {
            newIndex -= this._$itemList.length;
          }
          activeIndex.push(newIndex);
        }
      } else {
        for (i = 0, length = this._activeItems.length; i < length; i++) {
          index = this._activeItems[i];
          newIndex = --index;
          if (newIndex < 0) {
            newIndex += this._$itemList.length;
          }
          activeIndex.push(newIndex);
        }
      }
      this._activeItems = activeIndex;
      this._setActiveClass();
      this._updateIndicators();
      this._transform = transform;
      this._$items.style.transform = 'translateX(' + transform + '%)';
      this._$items.dispatchEvent(new CustomEvent('transition-start', {bubbles: true}));
    };
    
    // _moveToNext
    ChiefSlider.prototype._moveToNext = function() {
      this._direction = 'next';
      this._move();
    };
    
    // _moveToPrev
    ChiefSlider.prototype._moveToPrev = function() {
      this._direction = 'prev';
      this._move();
    };
    
    // _moveTo
    ChiefSlider.prototype._moveTo = function(index) {
      var $indicatorList = this._$indicatorList;
      var nearestIndex = null;
      var diff = null;
      var i;
      var length;
      for (i = 0, length = $indicatorList.length; i < length; i++) {
        var $indicator = $indicatorList[i];
        if ($indicator.classList.contains(CLASS_INDICATOR_ACTIVE)) {
          var slideTo = +$indicator.dataset.slideTo;
          if (diff === null) {
            nearestIndex = slideTo;
            diff = Math.abs(index - nearestIndex);
          } else {
            if (Math.abs(index - slideTo) < diff) {
              nearestIndex = slideTo;
              diff = Math.abs(index - nearestIndex);
            }
          }
        }
      }
      diff = index - nearestIndex;
      if (diff === 0) {
        return;
      }
      this._direction = diff > 0 ? 'next' : 'prev';
      for (i = 1; i <= Math.abs(diff); i++) {
        this._move();
      }
    };
    
    // _autoplay
    ChiefSlider.prototype._autoplay = function(action) {
      if (!this._config.autoplay) {
        return;
      }
      if (action === 'stop') {
        clearInterval(this._intervalId);
        this._intervalId = null;
        return;
      }
      if (this._intervalId === null) {
        this._intervalId = setInterval(
            function() {
              this._direction = 'next';
              this._move();
            }.bind(this),
            this._config.interval
        );
      }
    };
    
    // _refresh
    ChiefSlider.prototype._refresh = function() {
      // create some constants
      var $itemList = this._$itemList;
      var widthItem = $itemList[0].offsetWidth;
      var widthWrapper = this._$wrapper.offsetWidth;
      var itemsInVisibleArea = Math.round(widthWrapper / widthItem);
    
      if (itemsInVisibleArea === this._itemsInVisibleArea) {
        return;
      }
      
      this._autoplay('stop');
    
      this._$items.classList.add(SLIDER_TRANSITION_OFF);
      this._$items.style.transform = 'translateX(0)';
    
      // setting properties after reset
      this._widthItem = widthItem;
      this._widthWrapper = widthWrapper;
      this._itemsInVisibleArea = itemsInVisibleArea;
      this._transform = 0;
      this._transformStep = 100 / itemsInVisibleArea;
      this._balancingItemsFlag = false;
      this._activeItems = [];
    
      // setting order and translate items after reset
      for (var i = 0, length = $itemList.length; i < length; i++) {
        var $item = $itemList[i];
        var position = i;
        $item.dataset.index = position;
        $item.dataset.order = position;
        $item.dataset.translate = 0;
        $item.style.transform = 'translateX(0)';
        if (position < itemsInVisibleArea) {
          this._activeItems.push(position);
        }
      }
    
      this._setActiveClass();
      this._updateIndicators();
      window.requestAnimationFrame(
          function() {
            this._$items.classList.remove(SLIDER_TRANSITION_OFF);
          }.bind(this)
      );
    
      // hide prev arrow for non-infinite slider
      if (!this._config.loop) {
        if (this._$controlPrev) {
          this._$controlPrev.classList.add(CLASS_CONTROL_HIDE);
        }
        return;
      }
    
      // translate last item before first
      var count = $itemList.length - 1;
      var translate = -$itemList.length * 100;
      $itemList[count].dataset.order = -1;
      $itemList[count].dataset.translate = -$itemList.length * 100;
      $itemList[count].style.transform = 'translateX('.concat(translate, '%)');
      // update values of extreme properties
      this.__refreshExtremeValues();
      // calling _autoplay
      this._autoplay();
    };
    
    // public
    ChiefSlider.prototype.next = function() {
      this._moveToNext();
    };
    ChiefSlider.prototype.prev = function() {
      this._moveToPrev();
    };
    ChiefSlider.prototype.moveTo = function(index) {
      this._moveTo(index);
    };
    ChiefSlider.prototype.refresh = function() {
      this._refresh();
    };
    /* My styles Start */
    
      *,
        *::before,
        *::after {
          box-sizing: border-box;
        }
    
        body {
          margin: 0;
          font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
            'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
            'Segoe UI Symbol';
        }
    
        .container {
          max-width: 100%;
          max-height: 100%;
          margin: 0 auto;
        }
    
        .slider__wrapper {
          overflow: hidden;
        }
    
        .slider__item {
          flex: 0 0 25%;
          max-width: 25%;
          height: 100vh;
          display: flex;
          justify-content: center;
          align-items: center;
          color: rgba(255,255,255, 0.8);
          font-size: 7rem;
        }
    
        .slider__item:nth-child(1) {
          background-color: #f44336;
        }
    
        .slider__item:nth-child(2) {
          background-color: #9c27b0;
        }
    
        .slider__item:nth-child(3) {
          background-color: #3f51b5;
        }
    
        .slider__item:nth-child(4) {
          background-color: #03a9f4;
        }
    
        .slider__item:nth-child(5) {
          background-color: #4caf50;
        }
    
    /* My styles End */
    
    /*!
    * chiefSlider
    *   site: https://itchief.ru/javascript/slider
    *   github: https://github.com/itchief/ui-components
    *
    * Copyright 2018-2021 Alexander Maltsev
    * Licensed under MIT (https://github.com/itchief/ui-components/blob/master/LICENSE)
    */
    
    .slider {
      position: relative;
    }
    
    .slider__container {
      overflow: hidden;
    }
    
    .slider__wrapper {
      /*overflow: hidden;*/
    }
    
    .slider__items {
      display: flex;
      transition: transform 0.5s ease;
    }
    
    .slider_disable-transition {
      transition: none;
    }
    
    .slider__item {
      flex: 0 0 100%;
      max-width: 100%;
      user-select: none;
    }
    
    /* кнопки влево и вправо */
    
    .slider__control {
      position: absolute;
      top: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 40px;
      color: #fff;
      text-align: center;
      height: 50px;
      transform: translateY(-50%);
      background: rgba(0, 0, 0, 0.2);
    }
    
    .slider__control_hide {
      display: none;
    }
    
    .slider__control[data-slide='prev'] {
      left: 0;
    }
    
    .slider__control[data-slide='next'] {
      right: 0;
    }
    
    .slider__control:hover,
    .slider__control:focus {
      color: #fff;
      text-decoration: none;
      outline: 0;
      background: rgba(0, 0, 0, 0.3);
    }
    
    .slider__control::before {
      content: '';
      display: inline-block;
      width: 20px;
      height: 20px;
      background: transparent no-repeat center center;
      background-size: 100% 100%;
    }
    
    .slider__control[data-slide='prev']::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E");
    }
    
    .slider__control[data-slide='next']::before {
      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E");
    }
    
    /* индикаторы */
    
    .slider__indicators {
      position: absolute;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 15;
      display: flex;
      justify-content: center;
      padding-left: 0;
      margin-right: 15%;
      margin-left: 15%;
      list-style: none;
      margin-top: 0;
      margin-bottom: 0;
    }
    
    .slider__indicators li {
      box-sizing: content-box;
      flex: 0 1 auto;
      width: 30px;
      height: 5px;
      margin-right: 3px;
      margin-left: 3px;
      text-indent: -999px;
      cursor: pointer;
      background-color: rgba(255, 255, 255, 0.5);
      background-clip: padding-box;
      border-top: 15px solid transparent;
      border-bottom: 15px solid transparent;
    }
    
    .slider__indicators li.active {
      background-color: rgba(255, 255, 255, 0.9);
    }
    <body>
      <div class="container">
        <div class="slider">
          <div class="slider__wrapper">
            <div class="slider__items">
              <div class="slider__item">
                <!-- Контент 1 слайда -->
                1
              </div>
              <div class="slider__item">
                <!-- Контент 2 слайда -->
                2
              </div>
              <div class="slider__item">
                <!-- Контент 3 слайда -->
                3
              </div>
              <div class="slider__item">
                <!-- Контент 4 слайда -->
                4
              </div>
              <div class="slider__item">
                <!-- Контент 5 слайда -->
                5
              </div>
            </div>
          </div>
          <a href="#" class="slider__control" data-slide="prev"></a>
          <a href="#" class="slider__control" data-slide="next"></a>
        </div>
      </div>
    </body>