'How to speed up performance on my drag and drop?

Update #2 And... transition was stuck at .35s. Not sure why my CSS wasn't updating : (

UPDATE: Is there a way to use requestAnimationFrame to pull this off?

I have a rotating image reel, and I'd like to be able to swipe left and right and switch to the next or previous image (rotating all the image in the set).

I use the touchmove event and css transform: translate property to move the image, so the swiping left and right is responsive the users touch.

Namely, between when touchstart, and touchend fire, the touchmove event is used to move the actual image, so the user can see something is happening. But,... it's wicked slow. How do I get it to be much more responsive?

Here's the code:

!(function () {
  "use strict"
  window.addEventListener('load', function (event) {

    var modules = document.querySelectorAll('a.module')
    var interval

    // This function rotates the modules every 7500 milliseconds.
    function initiateInterval () {
      interval = setInterval(function () {
        modules.forEach(function (module) {
          rotateToNext(module)
        })
      }, 2500)
    }

    initiateInterval() // Kick things off on page load.

    //Be ready to manually switch things on click.
    modules.forEach(function (module) {
      module.addEventListener('click', (event) => switchToManual(module) )
    })

    // Disable clicking while adjusting manually.
    // Then reinitiate the iterval and enable clicking again.
    function switchToManual (module) {
      disableButtons()
      clearInterval(interval)
      cycleTargetToCenter(module, function () {
        initiateInterval()
        enableButtons()
      })
    }

    // Rotate on swipe left or right.
    modules.forEach(function (module) {
      var startPoint
      var endPoint
      module.addEventListener('touchstart', function (event) {
        disableButtons()
        clearInterval(interval)
        return startPoint = event.changedTouches[0].screenX
      })
      module.addEventListener('touchmove', function (event) {
        module.style.transform = `translate(${(event.changedTouches[0].screenX - startPoint)}px ,0px)`
      })
      module.addEventListener('touchend', function (event) {
        module.style.transform = ''
        endPoint = event.changedTouches[0].screenX
        if (endPoint > startPoint + 70) modules.forEach( (mod) => rotateToNext(mod) )
        if (endPoint < startPoint - 70) modules.forEach( (mod) => rotateToPrevious(mod) )
        initiateInterval()
        enableButtons()
      })

    })

    function disableButtons () {
      modules.forEach(function (module) {
        module.setAttribute('disabled', 'disabled')
      })
    }

    function enableButtons () {
      modules.forEach(function (module) {
        module.removeAttribute('disabled')
      })
    }

    function cycleTargetToCenter (module, func) {
      var currentPosition = decernCurrentPosition(module)
      if (currentPosition === 'position3') {
        return func()
      } else {
        var spins = decernNumberOfNeededRotations(module)
        for (let i = 0; i < spins; i += 1) {
          modules.forEach( (mod) => rotateToNext(mod) )
        }
        return func()
      }
    }

    function rotateToNext (module) {
      var currentPosition = decernCurrentPosition(module)
      var nextPosition = decernNextPosition(module)
      module.classList.remove(currentPosition)
      module.classList.add(nextPosition)
    }

    function rotateToPrevious (module) {
      var currentPosition = decernCurrentPosition(module)
      var previousPosition = decernPreviousPosition(module)
      module.classList.remove(currentPosition)
      module.classList.add(previousPosition)
    }

    function decernCurrentPosition (module) {
      if (module.classList.contains('position1')) return 'position1'
      if (module.classList.contains('position2')) return 'position2'
      if (module.classList.contains('position3')) return 'position3'
      if (module.classList.contains('position4')) return 'position4'
      if (module.classList.contains('position5')) return 'position5'
    }

    function decernNextPosition (module) {
      if (module.classList.contains('position1')) return 'position2'
      if (module.classList.contains('position2')) return 'position3'
      if (module.classList.contains('position3')) return 'position4'
      if (module.classList.contains('position4')) return 'position5'
      if (module.classList.contains('position5')) return 'position1'
    }

    function decernPreviousPosition (module) {
      if (module.classList.contains('position1')) return 'position5'
      if (module.classList.contains('position2')) return 'position1'
      if (module.classList.contains('position3')) return 'position2'
      if (module.classList.contains('position4')) return 'position3'
      if (module.classList.contains('position5')) return 'position4'
    }

    function decernNumberOfNeededRotations (module) {
      if (module.classList.contains('position1')) return 2
      if (module.classList.contains('position2')) return 1
      if (module.classList.contains('position4')) return 4
      if (module.classList.contains('position5')) return 3
    }

  })
}());
section.modules {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  overflow-x: hidden;
  height: 500px;
}
a.module {
  font-weight: normal;
  position: absolute;
  top: 5em;
  display: flex;
  justify-content: center;
  text-align: center;
  width: 295px;
  height: 295px;
  flex-shrink: 0;
  margin: 1em;
  transition: 1s;
}
a.module div.icon {
  position: absolute;
  left: 50%;
  margin-left: -45px;
  top: -45px;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 90px;
  height: 90px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 50%;
}
a.module div.copy {
  padding: 42px 2em 2em 2em;
  background: #fff;
  border-radius: 1em;
}
a.module div.copy h2 {
  font-size: 2em;
  margin: 0;
}
a.module div.copy h2 p.subtitle {
  font-size: 0.65em;
}
a.module.position1 {
  z-index: 1;
  transform: scale(0.6) translate(-270px, -90px);
  filter: drop-shadow(0 0 8px #bababa);
}
a.module.position2 {
  z-index: 3;
  transform: scale(0.8) translate(-400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}
a.module.position3 {
  z-index: 3;
  transform: scale(1);
  filter: drop-shadow(0 0 18px #bababa);
}
a.module.position4 {
  z-index: 2;
  transform: scale(0.8) translate(400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}
a.module.position5 {
  z-index: 1;
  transform: scale(0.6) translate(270px, -90px);
  filter: drop-shadow(0 0 8px #bababa);
}
<section class="modules"><a class="module module1 position1">
    <div class="icon">
      <h2>💡</h2>
    </div>
    <div class="copy">
      <h2>Bulbs
        <p class="subtitle">How many light bulbs?</p>
      </h2>
      <p>La la la...</p>
    </div></a><a class="module module2 position2">
    <div class="icon">
      <h2>🗨️</h2>
    </div>
    <div class="copy">
      <h2>Words
        <p class="subtitle">How many words?</p>
      </h2>
      <p>La la la</p>
    </div></a><a class="module module3 position3">
    <div class="icon">
      <h2>🤔</h2>
    </div>
    <div class="copy">
      <h2>Queries
        <p class="subtitle">How many queries?</p>
      </h2>
      <p>La la la...</p>
    </div></a><a class="module module4 position4">
    <div class="icon">
      <h2>🧪</h2>
    </div>
    <div class="copy">
      <h2>Tubes
        <p class="subtitle">Quantas Tubes?</p>
      </h2>
      <p>La la la...</p>
    </div></a><a class="module module5 position5">
    <div class="icon">
      <h2>🤸</h2>
    </div>
    <div class="copy">
      <h2>Actions
        <p class="subtitle">And this too...?</p>
      </h2>
      <p>La la la...</p>
    </div></a></section>

The touch events are slow, it's touch and slide, and then the object almost trails behind like it's lagging. What gives?



Solution 1:[1]

Step 1: delete touchmove event
Step 2: change transition to like .5s

!(function() {
  "use strict"
  window.addEventListener('load', function(event) {

    var modules = document.querySelectorAll('a.module')
    var interval

    // This function rotates the modules every 7500 milliseconds.
    function initiateInterval() {
      interval = setInterval(function() {
        modules.forEach(function(module) {
          rotateToNext(module)
        })
      }, 2500)
    }

    initiateInterval() // Kick things off on page load.

    //Be ready to manually switch things on click.
    modules.forEach(function(module) {
      module.addEventListener('click', (event) => switchToManual(module))
    })

    // Disable clicking while adjusting manually.
    // Then reinitiate the iterval and enable clicking again.
    function switchToManual(module) {
      disableButtons()
      clearInterval(interval)
      cycleTargetToCenter(module, function() {
        initiateInterval()
        enableButtons()
      })
    }

    // Rotate on swipe left or right.
    modules.forEach(function(module) {
      var startPoint
      var endPoint
      module.addEventListener('touchstart', function(event) {
        disableButtons()
        clearInterval(interval)
        return startPoint = event.changedTouches[0].screenX
      })

      module.addEventListener('touchend', function(event) {
        module.style.transform = ''
        endPoint = event.changedTouches[0].screenX
        if (endPoint > startPoint + 70) modules.forEach((mod) => rotateToNext(mod))
        if (endPoint < startPoint - 70) modules.forEach((mod) => rotateToPrevious(mod))
        initiateInterval()
        enableButtons()
      })

    })

    function disableButtons() {
      modules.forEach(function(module) {
        module.setAttribute('disabled', 'disabled')
      })
    }

    function enableButtons() {
      modules.forEach(function(module) {
        module.removeAttribute('disabled')
      })
    }

    function cycleTargetToCenter(module, func) {
      var currentPosition = decernCurrentPosition(module)
      if (currentPosition === 'position3') {
        return func()
      } else {
        var spins = decernNumberOfNeededRotations(module)
        for (let i = 0; i < spins; i += 1) {
          modules.forEach((mod) => rotateToNext(mod))
        }
        return func()
      }
    }

    function rotateToNext(module) {
      var currentPosition = decernCurrentPosition(module)
      var nextPosition = decernNextPosition(module)
      module.classList.remove(currentPosition)
      module.classList.add(nextPosition)
    }

    function rotateToPrevious(module) {
      var currentPosition = decernCurrentPosition(module)
      var previousPosition = decernPreviousPosition(module)
      module.classList.remove(currentPosition)
      module.classList.add(previousPosition)
    }

    function decernCurrentPosition(module) {
      if (module.classList.contains('position1')) return 'position1'
      if (module.classList.contains('position2')) return 'position2'
      if (module.classList.contains('position3')) return 'position3'
      if (module.classList.contains('position4')) return 'position4'
      if (module.classList.contains('position5')) return 'position5'
    }

    function decernNextPosition(module) {
      if (module.classList.contains('position1')) return 'position2'
      if (module.classList.contains('position2')) return 'position3'
      if (module.classList.contains('position3')) return 'position4'
      if (module.classList.contains('position4')) return 'position5'
      if (module.classList.contains('position5')) return 'position1'
    }

    function decernPreviousPosition(module) {
      if (module.classList.contains('position1')) return 'position5'
      if (module.classList.contains('position2')) return 'position1'
      if (module.classList.contains('position3')) return 'position2'
      if (module.classList.contains('position4')) return 'position3'
      if (module.classList.contains('position5')) return 'position4'
    }

    function decernNumberOfNeededRotations(module) {
      if (module.classList.contains('position1')) return 2
      if (module.classList.contains('position2')) return 1
      if (module.classList.contains('position4')) return 4
      if (module.classList.contains('position5')) return 3
    }

  })
}());
section.modules {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  overflow-x: hidden;
  height: 500px;
}

a.module {
  font-weight: normal;
  position: absolute;
  top: 5em;
  display: flex;
  justify-content: center;
  text-align: center;
  width: 295px;
  height: 295px;
  flex-shrink: 0;
  margin: 1em;
  transition: .5s; // <-- edit this
}

a.module div.icon {
  position: absolute;
  left: 50%;
  margin-left: -45px;
  top: -45px;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 90px;
  height: 90px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 50%;
}

a.module div.copy {
  padding: 42px 2em 2em 2em;
  background: #fff;
  border-radius: 1em;
}

a.module div.copy h2 {
  font-size: 2em;
  margin: 0;
}

a.module div.copy h2 p.subtitle {
  font-size: 0.65em;
}

a.module.position1 {
  z-index: 1;
  transform: scale(0.6) translate(-270px, -90px);
  filter: drop-shadow(0 0 8px #bababa);
}

a.module.position2 {
  z-index: 3;
  transform: scale(0.8) translate(-400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}

a.module.position3 {
  z-index: 3;
  transform: scale(1);
  filter: drop-shadow(0 0 18px #bababa);
}

a.module.position4 {
  z-index: 2;
  transform: scale(0.8) translate(400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}

a.module.position5 {
  z-index: 1;
  transform: scale(0.6) translate(270px, -90px);
  filter: drop-shadow(0 0 8px #bababa);
}
<section class="modules">
  <a class="module module1 position1">
    <div class="icon">
      <h2>?</h2>
    </div>
    <div class="copy">
      <h2>Bulbs
        <p class="subtitle">How many light bulbs?</p>
      </h2>
      <p>La la la...</p>
    </div>
  </a>
  <a class="module module2 position2">
    <div class="icon">
      <h2>??</h2>
    </div>
    <div class="copy">
      <h2>Words
        <p class="subtitle">How many words?</p>
      </h2>
      <p>La la la</p>
    </div>
  </a>
  <a class="module module3 position3">
    <div class="icon">
      <h2>?</h2>
    </div>
    <div class="copy">
      <h2>Queries
        <p class="subtitle">How many queries?</p>
      </h2>
      <p>La la la...</p>
    </div>
  </a>
  <a class="module module4 position4">
    <div class="icon">
      <h2>?</h2>
    </div>
    <div class="copy">
      <h2>Tubes
        <p class="subtitle">Quantas Tubes?</p>
      </h2>
      <p>La la la...</p>
    </div>
  </a>
  <a class="module module5 position5">
    <div class="icon">
      <h2>?</h2>
    </div>
    <div class="copy">
      <h2>Actions
        <p class="subtitle">And this too...?</p>
      </h2>
      <p>La la la...</p>
    </div>
  </a>
</section>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sarout