What are some strategies for increasing efficiency in my drag and drop process?

Update #2 Wow, transition was stuck at .35s. My CSS just wasn't updating properly :(

UPDATE: Anyone know if requestAnimationFrame could help with this?

I've got a rotating image reel and I want users to be able to swipe left or right to switch to the next or previous image (rotating through all images in the set).

To achieve this, I'm using the touchmove event and the css property transform: translate to move the image, making the swiping action responsive to touch.

Specifically, between the firing of touchstart and touchend, the touchmove event is used to visually move the image so that users can see it responding. However, it's moving pretty slowly. How can I make it more responsive?

Here's my code snippet:

!(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
    }

  })
}());
.modules {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  overflow-x: hidden;
  height: 500px;
}
.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;
}
.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%;
}
.module div.copy {
  padding: 42px 2em 2em 2em;
  background: #fff;
  border-radius: 1em;
}
.module div.copy h2 {
  font-size: 2em;
  margin: 0;
}
.module div.copy h2 p.subtitle {
  font-size: 0.65em;
}
.module.position1 {
  z-index: 1;
  transform: scale(0.6) translate(-270px, -90px);
  filter: drop-shadow(0 0 8px #bababa);
}
.module.position2 {
  z-index: 3;
  transform: scale(0.8) translate(-400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}
.module.position3 {
  z-index: 3;
  transform: scale(1);
  filter: drop-shadow(0 0 18px #bababa);
}
.module.position4 {
  z-index: 2;
  transform: scale(0.8) translate(400px, -10px);
  filter: drop-shadow(0 0 12px #bababa);
}
.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 really sluggish โ€“ you slide your finger and the object seems to lag behind rather than follow smoothly. What could be causing this delay?

Answer โ„–1

First Step: Remove the touchmove event
Second Step: Adjust transition timing to something 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() // Set things in motion on page load.

    //Ready for manual switching on click.
    modules.forEach(function(module) {
      module.addEventListener('click', (event) => switchToManual(module))
    })

    // Temporarily disable clicking while making manual adjustments.
    // Then restart the interval and allow clicking again.
    function switchToManual(module) {
      disableButtons()
      clearInterval(interval)
      cycleTargetToCenter(module, function() {
        initiateInterval()
        enableButtons()
      })
    }

    // Rotate when swiping 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; // <-- adjust this as needed
}

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Maintaining a Multi-page template in PhoneGap: Best practices

I'm a beginner in Hybrid app development, currently using PhoneGap and Jquery Mobile. In my app, I have around 10 separate pages such as login.html, index.html, search.html, etc. My query is whether I should include all JS and CSS files on each indivi ...

Custom hooks in Next.js do not have access to the localStorage object

I've encountered an issue with my custom useLocalStorage hook. It works perfectly fine with create-react-app, but when I try to use it with Next.js, the value in the initial state on line 3 returns undefined. Is there a way to bypass server-side rend ...

Creating a capsule-shaped button using HTML and CSS:

I'm trying to create a button that mimics the design in the code snippet. Is this method the most effective way, or is there a simpler approach I should consider? It seems like a lot of work just to achieve rounded corners. #p1,#p2{ height:25px; ...

Adjust the child element's value by referencing the parent class name

I need to update the content of child elements within an HTML file based on the class name of their parent element, using JavaScript. While I have successfully achieved this for static values by creating a TreeWalker for text nodes, doing the same for dyn ...

How can I use Node.js Express to send a response in a file format like JavaScript or another type?

Currently, I have a piece of code that successfully reads the 'example.js' file and sends it to the client as requested. app.get('/mods/example.js', function(req, res) { fs.readFile('./mods/example.js', {encod ...

Glitch discovered in the if statement implementation in PHP and HTML

<img id="post_like_btn_<?php echo $post_info['id']; ?>" class="post_like_btn" <?php $like_result = data_like($dbc, $user_info['id']); while($like_info = mysqli_fetch_assoc($like_result)){ if($post_info['id' ...

Creating a full-screen background with an rgba overlay using CSS

I recently encountered an issue with a fixed, fullscreen background image on my website. I initially applied the background image to the HTML's CSS instead of the body's CSS. To add a black overlay with lowered opacity, I included the following c ...

Ways to stop a background image from repeating?

<div style="background-image: url('https://i.ibb.co/v1B855w/bg15.png'); color: #000000; background-color: #000000; background-attachment: fixed; text-align: center;"><img src="https://i.ibb.co/L6zQY0S/name6.png" /> ...

When I incorporate JavaScript logic into my navigation, the Anchor Links fail to work properly

Currently facing an issue with my navigation bar where the category jump labels should change their bootstrap class when the corresponding heading is visible in the viewport. While everything works fine up to this point, adding the second event listener fo ...

React filtering displaying array elements that appear single time

I've been working on this React code to filter and search items based on user input. The issue I'm facing is that when I delete the text input and try again, the filtered items disappear and don't show up unless I reload the page. I'm c ...

Online application for saving a vast quantity of information on the user's device

Is there a way for a web application to store an extensive amount of data client-side, allowing for millions of records to be accessed offline by users exclusively on Chrome? I initially considered indexedDb, but I discovered it becomes almost unusable wi ...

The Vue Watch feature fails to trigger when incorporating axios

Hello everyone, I am facing an issue with my code that involves fetching data from a database using axios. The problem is that the watch function is not triggering in the .then() block. Below is the snippet of code I am currently working with. Thank you ...

The droplist functionality in jQuery does not seem to be functioning properly within an ASP.NET MVC 5

After adding an external theme to my project and writing a script for listing data in a dropdown list on a separate page, I encountered an issue where the script works on other pages but not on the Layout theme page. HomeController Note: The partial view ...

Determine the data type of a property within a JavaScript object

I am currently working with a javascript object that looks like this: venue = { id: 0, name: '', venueimage_set: [ { imageurl: '', }, ]... At a later point in my code, I need to modify the object ...

The straightforward use of XMLHttpRequest to retrieve the response xhttp.responseText is not functioning properly

I am facing an issue where this.responseText is not returning the content of the file. Can someone assist me in solving this problem? Thank you. Console.log also does not return the content of the file. function loadMegaContent() { var xhttp = new XMLHtt ...

Multiple jQuery AJAX requests triggered in a click event handler

I am in the process of developing a PHP web application and utilizing the datatables jQuery plugin along with jQuery AJAX calls to create a dynamic table for editing, deleting, and adding elements. Although it appears to be working correctly, I've not ...

Conflicting issues with jQuery's load() method

I am facing an issue with loading two HTML pages into a single div. I have index.html and try.html in the root folder, where try.html is loaded into index.html's div (#content) when Button 01 is clicked on index.html. The problem arises when I further ...

AngularJS SmartyUI position not dynamically updating on SmartyStreets plugin

In my angularJS application, I am utilizing SmartyStreets' LiveAddress for address validation and autofilling two fields in a form. After the user submits the form, a message (either success or failure) is displayed in a div above the form. However, t ...

Delaying Variable Assignment in Node.js until Callback Function Completes

I am currently working with Node.js, Express, MongoDB, and Mongoose in my project. One specific task involves fetching the largest id number of a document from the MongoDB database and passing it back to the program. To better organize my code, I moved thi ...

Implementing clickable actions to add new entries in a React.js application (using Redux toolkit)

I am currently working on my PET project using Redux toolkit and encountering some issues with inputs. When I add an input on click, it gets added correctly, but I am unsure if it is being added in the right place (it should be added in the ITEMS array). A ...