<main id="slide">
  <section class="slides">

    <article data-slide="0" class="slide slide--beauty slide--active">
      <svg class="svg" viewBox="0 0 1500 750">
        <clipPath id="clip-00">
          <path d="">
            <animate
              dur=""
              repeatCount=".5"
              attributeName="d"
              restart="whenNotActive"
              values=""
              keySplines=""
              calcMode="spline"
              fill="freeze">
          </path>
        </clipPath>
        <image clip-path="url(#clip-00)" height="100%" width="100%" xlink:href="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/beauty.jpg" />
      </svg>
    </article>
    <div class="bg-slide bg-slide--beauty bg-slide--active"></div>

    <article data-slide="1" class="slide slide--girl">
      <svg class="svg" viewBox="0 0 1500 750">
        <clipPath id="clip-01">
          <path d="">
            <animate
              dur=""
              repeatCount=".5"
              attributeName="d"
              restart="whenNotActive"
              values=""
              keySplines=""
              calcMode="spline"
              fill="freeze">
          </path>
        </clipPath>
        <image clip-path="url(#clip-01)" height="100%" width="100%" xlink:href="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/girl.jpg" />
      </svg>
    </article>
    <div class="bg-slide bg-slide--girl"></div>

    <article data-slide="2" class="slide slide--model">
      <svg class="svg" viewBox="0 0 1500 750">
        <clipPath id="clip-02">
          <path d="">
            <animate
              dur=""
              repeatCount=".5"
              attributeName="d"
              restart="whenNotActive"
              values=""
              keySplines=""
              calcMode="spline"
              fill="freeze">
          </path>
        </clipPath>
        <image clip-path="url(#clip-02)" height="100%" width="100%" xlink:href="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/model.jpg" />
      </svg>
    </article>
    <div class="bg-slide bg-slide--model"></div>

    <article data-slide="3" class="slide slide--snoe">
      <svg class="svg" viewBox="0 0 1500 750">
        <clipPath id="clip-03">
          <path d="">
            <animate
              dur=""
              repeatCount=".5"
              attributeName="d"
              restart="whenNotActive"
              values=""
              keySplines=""
              calcMode="spline"
              fill="freeze">
          </path>
        </clipPath>
        <image clip-path="url(#clip-03)" height="100%" width="100%" xlink:href="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/snow.jpg" />
      </svg>
    </article>
    <div class="bg-slide bg-slide--snow"></div>

    <article data-slide="4" class="slide slide--woman">
      <svg class="svg" viewBox="0 0 1500 750">
        <clipPath id="clip-04">
          <path d="">
            <animate
              dur=""
              repeatCount=".5"
              attributeName="d"
              restart="whenNotActive"
              values=""
              keySplines=""
              calcMode="spline"
              fill="freeze">
            </path>
        </clipPath>
        <image clip-path="url(#clip-04)" height="100%" width="100%" xlink:href="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/woman.jpg" />
      </svg>
    </article>
    <div class="bg-slide bg-slide--woman"></div>

  </section>
  
  <nav class="nav">
    <button class="slide__left btn" data-goto="3" type="button">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H6M12 5l-7 7 7 7"/></svg>
    </button>
    <ul class="slide__nav">
      <li><button class="btn btn--active js-nav" data-goto="0" type="button"><span class="visually-hidden">Slide </span>1</button></li>
      <li><button class="btn js-nav" data-goto="1" type="button"><span class="visually-hidden">Slide </span>2</button></li>
      <li><button class="btn js-nav" data-goto="2" type="button"><span class="visually-hidden">Slide </span>3</button></li>
      <li><button class="btn js-nav" data-goto="3" type="button"><span class="visually-hidden">Slide </span>4</button></li>
      <li><button class="btn js-nav" data-goto="4" type="button"><span class="visually-hidden">Slide </span>5</button></li>
    </ul>
    <button class="slide__right btn" data-goto="1" type="button">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h13M12 5l7 7-7 7"/></svg>
    </button>
  </nav>
</main>
<div class="open-modal">
  <button class="js-open-modal" type="button">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="21" x2="4" y2="14"></line><line x1="4" y1="10" x2="4" y2="3"></line><line x1="12" y1="21" x2="12" y2="12"></line><line x1="12" y1="8" x2="12" y2="3"></line><line x1="20" y1="21" x2="20" y2="16"></line><line x1="20" y1="12" x2="20" y2="3"></line><line x1="1" y1="14" x2="7" y2="14"></line><line x1="9" y1="8" x2="15" y2="8"></line><line x1="17" y1="16" x2="23" y2="16"></line></svg>
  </button>
  <button class="js-close-modal" type="button">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
  </button>
</div>
<div class="modal">
  <div class="modal__content">
    <section class="section section--active">
      <p class="section__title">Quadratic bottom</p>
      <img src="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/quadratic-bottom.png" alt="">
      <footer class="dur">
        <label class="label-dur">
          Tiempo animación (ms)
          <input class="btn-dur js-btn-dur" type="number" min="100" max="30000" value="1800">
        </label>
        <button class="btn-save" data-setting="setting01" type="button">Usar</button>
      </footer>
    </section>
    <section class="section">
      <p class="section__title">Quadratic left</p>
      <img src="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/quadratic-left.png" alt="">
      <footer class="dur">
        <label class="label-dur">
          Tiempo animación (ms)
          <input class="btn-dur js-btn-dur" type="number" min="100" max="30000" value="2000">
        </label>
        <button class="btn-save" data-setting="setting02" type="button">Usar</button>
      </footer>
    </section>
    <section class="section">
      <p class="section__title">Curve</p>
      <img src="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/curve.png" alt="">
      <footer class="dur">
        <label class="label-dur">
          Tiempo animación (ms)
          <input class="btn-dur js-btn-dur" type="number" min="100" max="30000" value="2300">
        </label>
        <button class="btn-save" data-setting="setting03" type="button">Usar</button>
      </footer>
    </section>
    <section class="section">
      <p class="section__title">Morph</p>
      <img src="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/morph.png" alt="">
      <footer class="dur">
        <label class="label-dur">
          Tiempo animación (ms)
          <input class="btn-dur js-btn-dur" type="number" min="100" max="30000" value="2500">
        </label>
        <button class="btn-save" data-setting="setting04" type="button">Usar</button>
      </footer>
    </section>
    <section class="section">
      <p class="section__title">Rhombus</p>
      <img src="https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/rhombus.png" alt="">
      <footer class="dur">
        <label class="label-dur">
          Tiempo animación (ms)
          <input class="btn-dur js-btn-dur" type="number" min="100" max="30000" value="1500">
        </label>
        <button class="btn-save" data-setting="setting05" type="button">Usar</button>
      </footer>
    </section>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400&display=swap');
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
	display: block;
}
* {
  padding: 0;
  margin: 0;
  &, &::after, *::before {
    box-sizing: border-box;
  }
}
ul,
figure {
  margin-block-start: 0;
  margin-block-end: 0;
  margin-inline-start: 0;
  margin-inline-end: 0;
}
ol, ul {
	list-style: none;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
  cursor: pointer;
  border: 0;
  padding: 0;
  background-color: transparent;
  -webkit-appearance: button;
}

html {
  font-family: 'Open Sans', sans-serif;
  font-weight: 400;
  line-height: 1.5;
  scroll-behavior: smooth;
  -webkit-tap-highlight-color: transparent;
}

.visually-hidden {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.slides {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  grid-gap: 0;
}
.slide {
  grid-area: 1 / 1 / 1 / 1;
  visibility: hidden;

  &--active {
    visibility: visible;
  }

  &__nav {
    display: flex;
    justify-content: center;
    z-index: 2;
    margin: 0 .7em;
    li {
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
  &__left,
  &__right {
    svg {
      width: 1.2em;
      height: 1.2em;
      pointer-events: none;
    }
  }
  .svg {
    display: block;
    max-height: calc(100vh - 2.5em);
    margin: auto;
  }
}
.bg-slide {
  grid-area: 1 / 1 / 1 / 1;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  visibility: hidden;

  &--active {
    visibility: visible;
  }
  &--beauty {
    background-image: url(https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/beauty.jpg);
  }
  &--girl {
    background-image: url(https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/girl.jpg);
  }
  &--model {
    background-image: url(https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/model.jpg);
  }
  &--snow {
    background-image: url(https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/snow.jpg);
  }
  &--woman {
    background-image: url(https://raw.githubusercontent.com/ivanalbizu/Slider-SVG-Animate-Path/master/src/img/woman.jpg);
  }
}
.nav {
  display: flex;
  justify-content: center;
}
.btn {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, .9);
  color: #fff;
  border: 1px solid rgba(0, 0, 0, .9);
  width: 2em;
  height: 2em;
  margin: 0.5em .2em;
  transition: all .7s ease-in 0s;
  &--active {
    background-color: #fff;
    color: rgba(0, 0, 0, 0.9);
    transition: all .2s ease-in 0s;
    pointer-events: none;
  }
}


// Not necessary. Use to show example paths animations
.open-modal {
  position: fixed;
  top: 10px;
  right: 18px;
  background-color: rgba(0, 0, 0, .9);
  border: 1px solid #fff;
  padding: .3em;
  z-index: 10;
  display: flex;
  button {
    display: flex;
  }
  .js-close-modal {
    display: none;
  }
}

.modal {
  position: fixed;
  right: 0;
  width: 350px;
  top: 0;
  bottom: 0;

  z-index: -9;
  visibility: hidden;
  img {
    max-width: 100%;
  }

  &__content {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    overflow-y: auto;
    background-color: rgba(0, 0, 0, .85);
    padding: 2.5em 1.5em;
    height: 100%;
    transform: translateY(-10px);
    transition: transform .3s ease;
    .section {
      color: #fff;
      padding: .7em 1em 1em;
      border: 1px dashed #fff;
      margin-bottom: 2em;
      &__title {
        font-size: .8em;
        letter-spacing: .2px;
        text-align: center;
        margin-bottom: .7em;
        text-transform: uppercase;
      }
      &--active {
        border-style: solid;
      }
    }
  }
  .dur {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    margin-top: .5em;
  }
  .btn-save {
    color: #fff;
    border: 1px solid #fff;
    padding: .4em 2.2em;
    text-transform: uppercase;
  }
  .btn-dur {
    border: 0;
    padding: .45em;
    margin-top: .4em;
  }
  .label-dur {
    font-size: .7em;
  }
}
.modal-active {
  margin-right: 340px;
  .open-modal {
    .js-close-modal {
      display: flex;
    }
    .js-open-modal {
      display: none;
    }
  }
  .modal {
    z-index: 9;
    visibility: visible;
    &__content {
      transform: translateY(0);
      transition: transform .3s ease;
    }
  }
}
View Compiled
// SVG Animations tuto
// https://codeburst.io/svg-morphing-the-easy-way-and-the-hard-way-c117a620b65f
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animate

// SVG paths builder
// https://codepen.io/anthonydugois/full/mewdyZ

// Timing functions:
// http://franzheidl.github.io/keysplines/


// Settings
const setting01 = {
  dur: 1800,
  paths: [
    "M 0 750 Q 150 750 200 750 Q 250 750 300 750 Q 350 750 400 750 C 500 750 750 750 1500 750 L 1500 750 L 0 750 Z",
    "M 0 300 Q 150 100 200 300 Q 250 600 300 300 Q 350 50 400 300 C 500 750 750 50 1500 300 L 1500 750 L 0 750 Z",
    "M 0 0 Q 150 0 200 0 Q 250 0 300 0 Q 350 0 400 0 C 500 0 750 0 1500 0 L 1500 750 L 0 750 Z"
  ],
  keySplines: [
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39"
  ]
}
const setting02 = {
  dur: 2000,
  paths: [
    "M 0 0 Q 0 100 0 300 Q 0 550 0 600 Q 0 650 0 750 L 0 750 L 0 0 Z",
    "M 50 0 Q 900 100 450 300 Q 0 550 500 600 Q 900 650 50 750 L 0 750 L 0 0 Z",
    "M 700 0 Q 1450 100 950 300 Q 400 500 800 600 Q 1050 650 950 750 L 0 750 L 0 0 Z",
    "M 1100 0 Q 1450 100 1250 300 Q 900 550 1150 600 Q 1350 650 1500 750 L 0 750 L 0 0 Z",
    "M 1500 0 Q 1500 100 1500 300 Q 1500 550 1500 600 Q 1500 650 1500 750 L 0 750 L 0 0 Z"
  ],
  keySplines: [
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39"
  ]
}
const setting03 = {
  dur: 2300,
  paths: [
    "M 650 750 Q 1150 500 1100 0 L 1100 0 Q 1150 500 650 750 Z",
    "M 650 750 Q 1150 500 1100 0 L 1150 0 Q 1200 500 750 750 Z",
    "M 200 750 Q 800 500 800 0 L 1500 0 Q 1500 500 1200 750 Z",
    "M 0 750 Q 200 500 200 0 L 1500 0 Q 1500 500 1500 750 Z",
    "M 0 750 Q 0 500 0 0 L 1500 0 Q 1500 500 1500 750 Z"
  ],
  keySplines: [
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39"
  ]
}
const setting04 = {
  dur: 2500,
  paths: [
    "M 650 500 Q 650 500 650 500 Q 650 500 650 500 Q 650 500 650 500 C 650 500 650 500 650 500",
    "M 500 550 Q 400 400 500 450 Q 700 550 550 350 Q 500 250 700 400 C 800 450 550 650 500 550",
    "M 400 600 Q 100 350 300 400 Q 700 550 500 350 Q 250 100 800 350 C 1050 500 550 700 400 600",
    "M 250 750 Q 0 750 200 500 Q 300 400 200 250 Q 0 0 1050 150 C 1500 200 1450 750 250 750",
    "M 1500 750 Q 0 750 0 750 Q 0 400 0 0 Q 0 0 1500 0 C 1500 200 1500 750 1500 750"
  ],
  keySplines: [
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39"
  ]
}
const setting05 = {
  dur: 1500,
  paths: [
    "M 750 375 Q 525 375 450 375 Q 525 375 750 375 Q 975 375 1050 375 Q 975 375 750 375",
    "M 750 375 Q 525 450 450 375 Q 525 300 750 375 Q 975 300 1050 375 Q 975 450 750 375",
    "M 750 600 Q 525 450 450 375 Q 525 300 750 150 Q 975 300 1050 375 Q 975 450 750 600",
    "M 750 750 Q 150 600 0 375 Q 150 150 750 0 Q 1350 150 1500 375 Q 1350 600 750 750",
    "M 1500 750 Q 150 750 0 750 Q 0 0 0 0 Q 1500 0 1500 0 Q 1500 750 1500 750"
  ],
  keySplines: [
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39",
    "0.57 0.63 0.51 0.39"
  ]
}


class Slides {
  constructor(el, setting) {
    this.DOM = { el: el }
    this.DOM.left = this.DOM.el.querySelector('.slide__left')
    this.DOM.right = this.DOM.el.querySelector('.slide__right')
    this.DOM.slides = this.DOM.el.querySelectorAll('.slide')
    this.DOM.slidesCount = this.DOM.slides.length
    this.DOM.slidesBg = this.DOM.el.querySelectorAll('.bg-slide')
    this.DOM.slidesNavBtns = this.DOM.el.querySelectorAll('.slide__nav .js-nav')
    this.DOM.gotoBtns = this.DOM.el.querySelectorAll('[data-goto]')
    this.isAnimating = false
    this.touchStartX = 0
    this.init(setting)
    this._addEventListeners()
  }

  init(setting) {
    this.DOM.slides.forEach(slide => {
      const path = slide.querySelector('clipPath path')    
      const animate = path.querySelector('animate')

      path.setAttributeNS(null, 'd', setting.paths[0])
      animate.setAttributeNS(null, 'values', arrayMirrorToString(setting.paths))
      animate.setAttributeNS(null, 'keySplines', arrayMirrorToString(setting.keySplines))
      animate.setAttributeNS(null, 'dur', `${setting.dur}ms`)
    })
  }

  _addEventListeners() {
    this.DOM.gotoBtns.forEach(nav => {
      nav.addEventListener('click', event => {
        if (this.isAnimating) return

        const goto = event.target.getAttribute('data-goto')
        const current = this.DOM.el.querySelector('.slide--active').getAttribute('data-slide')

        this.navigate(current, goto)
      })
    })
    this.DOM.slides.forEach(slide => {
      slide.nextElementSibling.addEventListener('touchstart', this.handleTouchStart.bind(this), false)
      slide.nextElementSibling.addEventListener('touchend', this.handleTouchEnd.bind(this), false)
    })
  }

  navigate(from, to) {
    this.isAnimating = true

    this.DOM.slidesNavBtns.forEach(nav => nav.classList.remove('btn--active'))

    this.DOM.left.setAttribute('data-goto', `${to == 0 ? this.DOM.slidesCount - 1 : +to-1}`)
    this.DOM.right.setAttribute('data-goto', `${to == this.DOM.slidesCount - 1 ? 0 : +to+1}`)

    const currentSlide = this.DOM.slides[from]
    const nextSlide = this.DOM.slides[to]
    const currentBg = this.DOM.slidesBg[from]
    const nextBg = this.DOM.slidesBg[to]

    const animate = nextSlide.querySelector('animate')

    animate.beginElement()
    setTimeout(() => {
      nextSlide.style.zIndex = 1
      nextSlide.classList.add('slide--active')

      animate.addEventListener('endEvent', () => {
        this.DOM.slidesNavBtns[to].classList.add('btn--active')
        nextSlide.style.zIndex = -1
        currentSlide.classList.remove('slide--active')
        currentBg.classList.remove('bg-slide--active')
        nextBg.classList.add('bg-slide--active')

        this.isAnimating = false
      })
    }, 1)

  }

  handleTouchStart(event) {
    this.touchStartX = event.touches[0].pageX
  }

  handleTouchEnd(event) {
    const moveX = event.changedTouches[event.changedTouches.length-1].pageX - this.touchStartX
    if (moveX < -10) this.DOM.right.click()
    else if (moveX > 10) this.DOM.left.click()
  }

}

const arrayMirrorToString = arr => {
  let newArr = [...arr].reverse()
  if (newArr.length % 2 != 0) newArr.shift()

  return arr.concat(newArr).join(';')
}

document.addEventListener('DOMContentLoaded', () => {

  const slide = new Slides(document.querySelector('#slide'), setting01)

  // Not necessary. Use to show example paths animations
  document.querySelectorAll('[data-setting]').forEach(setting => {
    setting.addEventListener('click', event => {
      
      const target = event.target;
      const section = target.closest('.section')
      const dur = section.querySelector('.js-btn-dur').value
      
      if (dur > 30000) return alert ('Maximum value of 30 seconds for transition')

      document.querySelectorAll('[data-setting]').forEach(section => section.closest('.section').classList.remove('section--active'))
      section.classList.add('section--active')

      let settingObjet = {}

      switch (target.getAttribute('data-setting')) {
        case 'setting01':
          setting01.dur = dur
          settingObjet = setting01
          break;
        case 'setting02':
          setting02.dur = dur
          settingObjet = setting02
          break;
        case 'setting03':
          setting03.dur = dur
          settingObjet = setting03
          break;
        case 'setting04':
          setting04.dur = dur
          settingObjet = setting04
          break;
        case 'setting05':
          setting05.dur = dur
          settingObjet = setting05
          break;
        default:
          break;
      }

      slide.init(settingObjet)
    })
  })

  document.querySelector('.js-open-modal').addEventListener('click', () => {
    document.body.classList.add('modal-active')
  })
  document.querySelector('.js-close-modal').addEventListener('click', () => {
    document.body.classList.remove('modal-active')
  })

})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.