admin管理员组

文章数量:1125046

I've implemented a basic image carousel (similar to this example). However, I'm encountering an issue with the transition when looping from the first slide to the last, or vice-versa. Instead of smoothly transitioning to the adjacent slide, all images shift, creating a jarring visual effect. I want the transition to behave as if the carousel were a continuous loop, only showing the single slide change.

Here are my code.

const slidesContainer = document.getElementById("slides-container");
const dotsContainer = document.getElementById("dots-container");
const prevButton = document.getElementById("slide-arrow-prev");
const nextButton = document.getElementById("slide-arrow-next");
const images = ["img1", "img2", "img3"];
let slideIndex = 1;

document.addEventListener("DOMContentLoaded", () => {
  generateImages(images);
  setEventForButton(prevButton);
  setEventForButton(nextButton);
});

// Generate images and dots
const generateImages = (imageToGenerate) => {
  imageToGenerate.forEach((image, index) => {
    // Generate images
    const slideComponent = document.createElement("li");
    slideComponent.classList.add("slide");
    slideComponent.innerHTML = `
            <img src="=${image}.jpg" alt="Image ${index + 1}" />
        `;

    slidesContainer.appendChild(slideComponent);

    // Generate dots
    const dotComponent = document.createElement("li");
    dotComponent.classList.add("dot");
    if (index === 0) dotComponent.classList.add("active");
    dotComponent.addEventListener("click", () => {
      showSlide(index + 1);
    });
    dotsContainer.appendChild(dotComponent);
  });
};

// Set event for next button
const setEventForButton = (button) => {
  button.addEventListener("click", () => {
    if (button.id === "slide-arrow-prev") showSlide(slideIndex > 1 ? slideIndex - 1 : images.length);
    else showSlide(slideIndex < images.length ? slideIndex + 1 : 1);
  });
};

// Set slideshow
const showSlide = (n) => {
  const slides = document.querySelectorAll(".slide");
  const dots = document.querySelectorAll(".dot");

  const slideWidth = slides[0].clientWidth;
  slidesContainer.scrollLeft = slideWidth * (n - 1);

  dots.forEach((dot) => dot.classList.remove("active"));
  dots[n - 1].classList.add("active");
  slideIndex = n;
};
* {
  box-sizing: border-box;
}

body {
  max-width: 1440px;
  margin: auto;
}

.slider-wrapper {
  margin: 1rem;
  position: relative;
  overflow: hidden;
}

.slides-container {
  height: calc(100vh - 2rem);
  width: 100%;
  display: flex;
  scroll-behavior: smooth;
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
}

.slide-arrow {
  position: absolute;
  display: flex;
  top: 0;
  bottom: 0;
  margin: auto;
  height: 4rem;
  background-color: white;
  border: none;
  width: 2rem;
  font-size: 3rem;
  padding: 0;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 100ms;
}

.slide-arrow:hover,
.slide-arrow:focus {
  opacity: 1;
}

#slide-arrow-prev {
  left: 0;
  padding-left: 0.25rem;
  border-radius: 0 2rem 2rem 0;
}

#slide-arrow-next {
  right: 0;
  padding-left: 0.75rem;
  border-radius: 2rem 0 0 2rem;
}

.slide {
  width: 100%;
  height: 100%;
  flex: 1 0 100%;
}

.slide img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.dots-container {
  position: absolute;
  top: 76%;
  left: 49%;
  right: auto;
  transform: translateX(-50%);
  display: flex;
}

.dot {
  cursor: pointer;
  display: inline-block;
  width: 0.8rem;
  height: 0.8rem;
  margin: 0 2px;
  border-radius: 50%;
  background-color: gray;
  transition: background_color 0.6s ease;
}

.active,
.dot:hover {
  background-color: black;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Exercise 2</title>
  <link rel="stylesheet" href="./styles2.css" />
</head>

<body>
  <section class="slider-wrapper">
    <button class="slide-arrow" id="slide-arrow-prev">&#8249;</button>
    <button class="slide-arrow" id="slide-arrow-next">&#8250;</button>
    <!-- Generate images -->
    <ul class="slides-container" id="slides-container"></ul>

    <!-- Generate dots -->
    <ul class="dots-container" id="dots-container"></ul>
  </section>
  <script src="./index2.js"></script>
</body>

</html>

I've implemented a basic image carousel (similar to this example). However, I'm encountering an issue with the transition when looping from the first slide to the last, or vice-versa. Instead of smoothly transitioning to the adjacent slide, all images shift, creating a jarring visual effect. I want the transition to behave as if the carousel were a continuous loop, only showing the single slide change.

Here are my code.

const slidesContainer = document.getElementById("slides-container");
const dotsContainer = document.getElementById("dots-container");
const prevButton = document.getElementById("slide-arrow-prev");
const nextButton = document.getElementById("slide-arrow-next");
const images = ["img1", "img2", "img3"];
let slideIndex = 1;

document.addEventListener("DOMContentLoaded", () => {
  generateImages(images);
  setEventForButton(prevButton);
  setEventForButton(nextButton);
});

// Generate images and dots
const generateImages = (imageToGenerate) => {
  imageToGenerate.forEach((image, index) => {
    // Generate images
    const slideComponent = document.createElement("li");
    slideComponent.classList.add("slide");
    slideComponent.innerHTML = `
            <img src="https://placehold.co/600x400?text=${image}.jpg" alt="Image ${index + 1}" />
        `;

    slidesContainer.appendChild(slideComponent);

    // Generate dots
    const dotComponent = document.createElement("li");
    dotComponent.classList.add("dot");
    if (index === 0) dotComponent.classList.add("active");
    dotComponent.addEventListener("click", () => {
      showSlide(index + 1);
    });
    dotsContainer.appendChild(dotComponent);
  });
};

// Set event for next button
const setEventForButton = (button) => {
  button.addEventListener("click", () => {
    if (button.id === "slide-arrow-prev") showSlide(slideIndex > 1 ? slideIndex - 1 : images.length);
    else showSlide(slideIndex < images.length ? slideIndex + 1 : 1);
  });
};

// Set slideshow
const showSlide = (n) => {
  const slides = document.querySelectorAll(".slide");
  const dots = document.querySelectorAll(".dot");

  const slideWidth = slides[0].clientWidth;
  slidesContainer.scrollLeft = slideWidth * (n - 1);

  dots.forEach((dot) => dot.classList.remove("active"));
  dots[n - 1].classList.add("active");
  slideIndex = n;
};
* {
  box-sizing: border-box;
}

body {
  max-width: 1440px;
  margin: auto;
}

.slider-wrapper {
  margin: 1rem;
  position: relative;
  overflow: hidden;
}

.slides-container {
  height: calc(100vh - 2rem);
  width: 100%;
  display: flex;
  scroll-behavior: smooth;
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
}

.slide-arrow {
  position: absolute;
  display: flex;
  top: 0;
  bottom: 0;
  margin: auto;
  height: 4rem;
  background-color: white;
  border: none;
  width: 2rem;
  font-size: 3rem;
  padding: 0;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 100ms;
}

.slide-arrow:hover,
.slide-arrow:focus {
  opacity: 1;
}

#slide-arrow-prev {
  left: 0;
  padding-left: 0.25rem;
  border-radius: 0 2rem 2rem 0;
}

#slide-arrow-next {
  right: 0;
  padding-left: 0.75rem;
  border-radius: 2rem 0 0 2rem;
}

.slide {
  width: 100%;
  height: 100%;
  flex: 1 0 100%;
}

.slide img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.dots-container {
  position: absolute;
  top: 76%;
  left: 49%;
  right: auto;
  transform: translateX(-50%);
  display: flex;
}

.dot {
  cursor: pointer;
  display: inline-block;
  width: 0.8rem;
  height: 0.8rem;
  margin: 0 2px;
  border-radius: 50%;
  background-color: gray;
  transition: background_color 0.6s ease;
}

.active,
.dot:hover {
  background-color: black;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Exercise 2</title>
  <link rel="stylesheet" href="./styles2.css" />
</head>

<body>
  <section class="slider-wrapper">
    <button class="slide-arrow" id="slide-arrow-prev">&#8249;</button>
    <button class="slide-arrow" id="slide-arrow-next">&#8250;</button>
    <!-- Generate images -->
    <ul class="slides-container" id="slides-container"></ul>

    <!-- Generate dots -->
    <ul class="dots-container" id="dots-container"></ul>
  </section>
  <script src="./index2.js"></script>
</body>

</html>

Share Improve this question edited 2 days ago mplungjan 177k28 gold badges180 silver badges240 bronze badges asked 2 days ago Đông NguyễnĐông Nguyễn 32 bronze badges 1
  • I suggest you clone the first and last image and then use mod to keep the index inside the range - alternatively move the first visible image to the end after scroll – mplungjan Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 0

var doslide=2;
var mousepostmp;

function autoslideleft(){
setInterval(function(){
if(doslide){
var arrel=document.getElementsByClassName("slideboxesspan");
var len0=arrel.length;
var x=arrel[0].offsetWidth;
arrel[0].style.marginLeft=(x*-1)+"px";
setTimeout(function(){
arrel[0].style.marginLeft="0px";
document.getElementById("slideholderid").appendChild(arrel[0]);
for(var t=0;t<len0;t++){arrel[t].style.marginLeft="8px";}
},400);
}
},2000);
}

function slideleft(){ 
var arrel=document.getElementsByClassName("slideboxesspan");
var len0=arrel.length;
var x=arrel[0].offsetWidth;
arrel[0].style.marginLeft=(x*-1)+"px";
setTimeout(function(){
arrel[0].style.marginLeft="0px";
document.getElementById("slideholderid").appendChild(arrel[0]);
for(var t=0;t<len0;t++){arrel[t].style.marginLeft="8px";}
},400);
}

function slideright(){
var arrel=document.getElementsByClassName("slideboxesspan");
var containing=document.getElementById("slideholderid");
var len0=arrel.length;
var x=arrel[0].offsetWidth; 
var newel="<span class='slideboxesspan slideSize' style='transition:0.4s;margin-left:"+(x*-1)+"px;'>"+arrel[len0-1].innerHTML+"</span>";
containing.removeChild(arrel[len0-1]);
containing.innerHTML=newel+containing.innerHTML;
var arrel=document.getElementsByClassName("slideboxesspan");
setTimeout(function(){arrel[0].style.marginLeft=(0)+"px";
for(var t=0;t<len0;t++){arrel[t].style.marginLeft="8px";}
},50);
}

function slideact(st){
doslide=st;
}

function startonload(){
//autoslideleft();
}
body{overflow-x:hidden;-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;}
.slideholder{display:inline-flex;overflow:hidden;}
.slideboxesspan{transition:0.4s;margin-left:8px;}
.slideSize{width:40vw;height:40vw;/*silde size*/}
.imgSlide{width:100%;height:100%;}
<body onload="startonload();">

<div align="center">
<div id="slideholderid" align="center" class="slideholder slideSize">

<span class="slideboxesspan slideSize">
<div align="center" class="slideboxes slideSize">
<img src="3.jpg" class="imgSlide"/>
</div>
</span>

<span class="slideboxesspan">
<div align="center" class="slideboxes slideSize">
<img src="4.jpg" class="imgSlide"/>
</div>
</span>

<span class="slideboxesspan">
<div align="center" class="slideboxes slideSize">
<img src="5.jpg" class="imgSlide"/>
</div>
</span>

<span class="slideboxesspan">
<div align="center" class="slideboxes slideSize">
<img src="3.jpg" class="imgSlide"/>
</div>
</span>

<span class="slideboxesspan">
<div align="center" class="slideboxes slideSize">
<img src="4.jpg" class="imgSlide"/>
</div>
</span>

<span class="slideboxesspan">
<div align="center" class="slideboxes slideSize">
<img src="5.jpg" class="imgSlide"/>
</div>
</span>

</div>
</div>

<input type="button" value="<" onclick="slideleft();" style="background-color:red;"/>
<input type="button" value=">" onclick="slideright();" style="background-color:red;"/>

</body>

本文标签: