javascriptreactjsangularjsvue.jssvelte

How to make series of images to slide uniformly and horizontally with using JavaScript to change transform transition


I'm trying to slide series of images from right to left and I want the same images to repeat sliding infinitely and uniformly.

For example if 1, 2, 3, 4, 5 are the images

when 1st slide happens, the series of images should be 

2, 3, 4, 5, 1

when 2nd slide happens, the series of images should be 

3, 4, 5, 1, 2

when 3rd slide happens, the series of images should be

4, 5, 1, 2, 3

and so on and so forth

To solve this problem with Vue.js, this is my source code

<script setup lang="ts">
import {ref, onMounted, } from "vue";

let 
  imgs = ref<string[]>(['c1.png','c2.png','c3.png','c5.png','c6.png','c7.png']), 
  imgsref = ref<HTMLDivElement[]>([]) 
;

function translateFunction(el: HTMLDivElement,distance: string) {
  el.style.transform="translateX("+distance+")";
  el.style.transition=" all 2s";
}

onMounted(() => {
  
  let counter2 = 0, started = false, transitionend = false, counter1 = 0, i = 0, el = (document.getElementById("world") as HTMLDivElement), done = false;

  setInterval(() => {
    console.log(done+' '+transitionend+' '+started)
    if(done && transitionend && started === false) {
      let distance = -1*(
    (imgsref.value[i] as HTMLImageElement).offsetWidth+10 
    + 
    (imgsref.value[i-1] as HTMLImageElement).offsetWidth+10
      );
      translateFunction(el, distance + 'px');
      el.style.transition =" all 2s";
      left.value = -1*((imgsref.value[i-1] as HTMLImageElement).offsetWidth+10);
      left.value = 0
      el.scrollLeft = 0
      imgs.value.splice((i-1), 1);
      i--;
      counter1 = 0;
      started = true;
      counter2 = 0;
    }
    if(started === true) counter2++;
    console.log(counter2)
    if(counter2 === 50) {
      done = false;
      transitionend = false;
    }
  }, 10);

  setInterval(() => {
    if(done === false) {
      console.log('first');
      //left.value = 0;
      let distance = -1*((imgsref.value[i] as HTMLImageElement).offsetWidth+10);
      translateFunction(el, distance + 'px');
      el.style.transition =" all 2s";
      console.log("sliding...")
      i++;
      imgs.value.push(imgs.value[i-1]);
      done = true;
      started = false;
      counter2 = 0;
    }
    if(transitionend === false) counter1++;
    if(counter1 === 5 && done === true) {
      transitionend = true;
      console.log('transition ended')
    }
    console.log(counter1);
  }, 1000);
});
</script>

<template>
  <div class="w-100" style="background-color:black;border-bottom:1px solid #fff;padding:100px 0 100px 90px">
    <div class="w-100 h-100" style="overflow:hidden;">
      <div id="world" class="h-100">
        <ul
          class="list-style-none flex-box flex-direction-row p-0 h-100 w-100 m-0 flex-nowrap justify-content-start align-items-center"
        >
          <li 
            v-for="(img, i) in imgs" 
            :key="i+'WORLD-IMAGES'" 
            class="align-self-stretch"
            :ref="(el) => imgsref[i] = (el as HTMLLIElement)"
          >
            <div class="d-block" style="(i>0)?'padding-left:10px;padding-right:10px;':'padding-right:10px;'">
              <a class="d-block underline-none">
                <img :src="'./src/assets/images/'+img" class="h-100" />
              </a>
              <span class="d-block" style="padding:30px 0;color:#fff;">Dolce&Gabbana: a future under the banner of sustainability</span>
              <a style="padding-bottom:30px;color:#fff;" class="underline-none">
                DISCOVER MORE
              </a>
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<style scoped>
.list-style-none {
  list-style: none;
} 
.flex-box {
  display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
  display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
  display: -ms-flexbox; /* TWEENER - IE 10 */
  display: -webkit-flex; /* NEW - Chrome */
  display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.flex-direction-row {
  -ms-flex-direction: row !important;
  flex-direction: row !important;
} 
.p-0 {
  padding: 0;
} 
.h-100 {
  height: 100%;
} 
.w-100 {
  width: 100%;
} 
.m-0 {
  margin: 0;
} 
.flex-nowrap {
  -ms-flex-wrap: nowrap !important;
  flex-wrap: nowrap !important;
} 
.justify-content-start {
  -ms-flex-pack: start !important;
  justify-content: flex-start !important;
} 
.align-items-center {
  align-items: center !important;
}
.d-block {
  display: block;
}
</style>

When I tested the code, the images switches position exactly how I wanted them, but the transition doesn't animate with ease.

I have tried changing the number of seconds with hope that it will work but it doesn't animate smoothly. How can I solve this problem?


Solution

  • Finally solved this problem

    onMounted(() => {
    
      let counter2 = 0, started = false, transitionend = false, counter1 = 0, i = 0, el = (document.getElementById("world") as HTMLDivElement), done = false;
    
      setInterval(() => {
        if((done === true && transitionend === true) && started === false) {
      
          if(
            (-1*((imgsref.value[i-1] as HTMLImageElement).offsetWidth+10))
            ===
            (-1*((imgsref.value[i] as HTMLImageElement).offsetWidth+10))
          ) {
            left.value = -1*((imgsref.value[i] as HTMLImageElement).offsetWidth+10)-2;
          }
          else {
            left.value = -1*((imgsref.value[i] as HTMLImageElement).offsetWidth+10);
          }
          imgs.value.splice((i-1), 1);
          i--;
          counter2 = 0;
          counter1 = 0;
          started = true;
        }
        if((done === true && transitionend === true) && started === true) {
          counter2++;
        }
        if(counter2 === 5) {
          done = false;
          transitionend = false;
          started = false;
        }
      }, 1);
    
      setInterval(() => {
        if((done === false && transitionend === false) && started === false) {
          let distance = -1*((imgsref.value[i] as HTMLImageElement).offsetWidth+10);
          translateFunction(el, distance + 'px');
          i++;
          imgs.value.push(imgs.value[i-1]);
          el.style.transition =" all 2s";
          counter1 = 0;
          counter2 = 0;
          transitionend = true;
        }
        if(transitionend === true && started === false && done === false) {
          counter1++;
        }
        if(counter1 === 3) {
          done = true;
        }
      }, 1000);
    });