Vanilla JS无限循环轮播动画异常问题求助
无限循环轮播组件动画异常问题
我用原生JS实现了无限循环轮播组件,基础功能已完成,但存在动画异常:
- 滑动到轮播末尾时会直接跳回首张卡片
- 点击或拖拽首张卡片向前无法切换到最后一张,而是直接跳转
预期效果:
- 从最后一张滑动时,首张卡片无缝衔接在其后
- 首张卡片向前滑动时,最后一张卡片无缝衔接在其前
HTML代码
<div class="container layout--fluid"> <div id="bannerCarousel" draggable="true" class="container"> <div class="row" ondragstart="return false;" ondrop="return false;"> <div class="col-md-6 image-content" ondragstart="return false;" ondrop="return false;"> <img src="https://picsum.photos/200/300" alt="Becel" /> </div> <div class="col-md-6 text-content" ondragstart="return false;" ondrop="return false;"> <div> <h1>Title comes here</h1> <p>Description comes here</p> <a href="#" class="btn btn-primary">Read More</a> </div> </div> </div> <div class="row" ondragstart="return false;" ondrop="return false;"> <div class="col-md-6 image-content" ondragstart="return false;" ondrop="return false;"> <img src="https://picsum.photos/200/301" alt="Blueband" /> </div> <div class="col-md-6 text-content" ondragstart="return false;" ondrop="return false;"> <div> <h1>Title comes here</h1> <p>Description comes here</p> <a href="#" class="btn btn-primary">Read More</a> </div> </div> </div> <div class="row" ondragstart="return false;" ondrop="return false;"> <div class="col-md-6 image-content" ondragstart="return false;" ondrop="return false;"> <img src="https://picsum.photos/200/303" alt="Country Crock" /> </div> <div class="col-md-6 text-content" ondragstart="return false;" ondrop="return false;"> <div> <h1>Title comes here</h1> <p>Description comes here</p> <a href="#" class="btn btn-primary">Read More</a> </div> </div> </div> <div class="row" ondragstart="return false;" ondrop="return false;"> <div class="col-md-6 image-content" ondragstart="return false;" ondrop="return false;"> <img src="https://picsum.photos/200/306" alt="Country Crock" /> </div> <div class="col-md-6 text-content" ondragstart="return false;" ondrop="return false;"> <div> <h1>Title comes here</h1> <p>Description comes here</p> <a href="#" class="btn btn-primary">Read More</a> </div> </div> </div> </div> </div>
CSS代码
body { margin: 0px; padding: 0px; } .container { width: 100%; background-color: #0d3b30; position: relative; overflow: hidden; } #bannerCarousel { display: flex; flex-wrap: nowrap; position: relative; transition: all 1.5s ease; -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ overflow-x: scroll; cursor: grab; @media only screen and (max-width:900px) { gap: 0px; } } #bannerCarousel::-webkit-scrollbar { display: none; } #bannerCarousel>.row { display: grid; grid-template-columns: repeat(2, 50%); gap: 20px; flex: 0 0 85%; @media only screen and (max-width:900px) { grid-template-columns: repeat(1, 100%); flex: 0 0 65%; } } #bannerCarousel .image-content img { width: 100%; height: auto; max-width: 550px; } #bannerCarousel .text-content { display: flex; flex-direction: column; justify-content: center; gap: 20px; text-align: left; @media only screen and (max-width:900px) { text-align: center; padding-bottom: 60px; } } .text-content h1 { color: #fff; font-family: var(); font-size: 48px; font-style: normal; font-weight: 400; line-height: normal; margin-top: 0px; margin-bottom: 15px; } .text-content p { color: #fff; /* D-UpWir-Subheading */ font-family: sans-serif; font-size: 18px; font-style: normal; font-weight: 700; line-height: 28px; margin-top: 0px; /* 155.556% */ } .text-content a { display: flex; padding: 14px 40px 15px 40px; align-items: center; justify-content: center; gap: 10px; border-radius: 100px; background: var(--BB-Blue, #151E8A); max-width: 200px; box-sizing: border-box; color: #fff; text-decoration: none; font-size: 19px; font-weight: 700; @media only screen and (max-width:900px) { margin: 0 auto; } } .bullet-container { position: absolute; bottom: 20px; left: 50%; display: flex; flex-wrap: nowrap; gap: 10px; transform: translateX(-50%); } .bullet-container .bullet { width: 10px; height: 10px; border-radius: 50%; background-color: #fff; cursor: pointer; } .bullet-container .bullet.active{ background-color: red; }
JavaScript代码
let container = document.getElementById("bannerCarousel"); let scrollElement = container.querySelector(".row"); let scrollCount = container.children.length; //container.querySelector('img').ondragstart = function() { return false; }; class BannerCarousel { constructor(container, child) { this.slideContainer = container; this.slides = child; this.length = child.length; this.slideWidth = child[0].clientWidth; this.dragStart = 0; this.curActive = 0; } move(index) { let scrollValue = parseFloat(this.slideWidth) * index; if (screen.width <= 900) { scrollValue = parseFloat(this.slideWidth) * index - 60; } console.log(scrollValue); this.slideContainer.scroll({ left: scrollValue, top: 0, behavior: 'smooth' }) } prev() { this.curActive++; if (this.curActive >= this.length) { this.curActive = 0; } this.makeBulletActive(this.curActive); this.makeSlideActive(this.curActive); this.move(this.curActive) } next() { this.curActive--; if (this.curActive < 0) { this.curActive = this.length - 1; } this.makeBulletActive(this.curActive); this.makeSlideActive(this.curActive); this.move(this.curActive); } addDragEvent() { let _this = this; this.slideContainer.addEventListener("dragstart", function (event) { console.log("Drag start"); _this.dragStart = event.clientX; }) this.slideContainer.addEventListener("dragend", function (event) { console.log("Drag end"); let end = event.clientX; let dif = end - _this.dragStart; console.log(dif); if (dif < 0) { _this.prev(_this.curActive) console.log("Go right"); } else { _this.next(_this.curActive); console.log("Go left") } }) this.slideContainer.addEventListener("touchstart", function (event) { _this.dragStart = event.touches[0].clientX; }) this.slideContainer.addEventListener("touchend", function (event) { let end = event.changedTouches[0].clientX; let dif = end - _this.dragStart; if (dif < 0) { //prev(); console.log("Go right"); } else { //next(); console.log("Go left"); } }) } getChildElementIndex(node) { return Array.prototype.indexOf.call(node.parentNode.children, node); } makeBulletActive(target) { let container = document.querySelector(".bullet-container"); let bullets = container.querySelectorAll("span"); console.log(bullets); bullets.forEach((ele, index) => { ele.classList.toggle("active", index === target) }) } makeSlideActive(target) { this.slides.forEach((ele, index) => { ele.classList.toggle("active", index === target) }) } addBullet() { let bulletContainer = document.createElement("div"); bulletContainer.className = "bullet-container"; for (let i = 0; i < this.length; i++) { let bullet = document.createElement("span"); bullet.className = "bullet"; bulletContainer.appendChild(bullet); } this.slideContainer.parentElement.appendChild(bulletContainer); } addBulletClickEvent() { const _this = this; document.addEventListener("click", function (e) { if (e.target.className === "bullet") { let index = _this.getChildElementIndex(e.target); let scrollValue = parseFloat(_this.slideWidth) * index; _this.curActive = index; _this.makeBulletActive(index); _this.makeSlideActive(index); if (screen.width <= 900) { scrollValue = parseFloat(_this.slideWidth) * index - 60; } console.log(scrollValue); _this.slideContainer.scroll({ left: scrollValue, top: 0, behavior: 'smooth' }) } }) } } let new_carousel = new BannerCarousel(container, container.querySelectorAll(".row")); new_carousel.addBullet(); new_carousel.addBulletClickEvent(); new_carousel.makeBulletActive(new_carousel.curActive); new_carousel.makeSlideActive(new_carousel.curActive); new_carousel.addDragEvent();
内容的提问来源于stack exchange,提问作者Pranay kumar
相关产品推荐
相关产品推荐

