我打算写一个平滑过渡的轮播图,但是这里出现了一个小问题,从最后一个图片返回第一个图片的时候居然重头返回再进行过渡,并且在移动端时无法通过拖动来进行切换
HTML代码,滑动用的transform的translate3d实现的,用了Bootstrap5的框架
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rTTiRUKnSWaDu2FjhzWFl8/JuUZMlplyWE/djenb2LoKqkgLGfEGfSrL7XDLoB1M" crossorigin="anonymous">
<div class="slider">
<div class="slider-indicators">
<button class="active" data-to="0" tabindex="-1"></button>
<button data-to="1" tabindex="-1"></button>
<button data-to="2" tabindex="-1"></button>
</div>
<div class="slider-outer">
<div class="slider-inner">
<div class="slider-item">
<a href="#">
<img src="https://around.createx.studio/img/demo/food-blog/videos/03.jpg" loading="lazy">
<span>Gallery video caption</span>
</a>
</div>
<div class="slider-item">
<a href="#">
<img src="https://around.createx.studio/img/demo/food-blog/videos/01.jpg" loading="lazy">
<span>Gallery video caption</span>
</a>
</div>
<div class="slider-item">
<a href="#">
<img src="https://around.createx.studio/img/demo/food-blog/videos/02.jpg" loading="lazy">
<span>Gallery video caption</span>
</a>
</div>
<div class="slider-item">
<a href="#">
<img src="https://around.createx.studio/img/demo/food-blog/videos/03.jpg" loading="lazy">
<span>Gallery video caption</span>
</a>
</div>
<div class="slider-item">
<a href="#">
<img src="https://around.createx.studio/img/demo/food-blog/videos/01.jpg" loading="lazy">
<span>Gallery video caption</span>
</a>
</div>
</div>
</div>
</div>
CSS代码
.slider{
position: relative;
}
.slider .slider-indicators{
position: absolute;
top: 100%;
width: 100%;
padding-top: 1rem;
text-align: center;
white-space: nowrap;
}
[data-to] {
display: inline-block;
position: relative;
width: .75rem;
height: .75rem;
margin: 0 .25rem;
padding: 0;
border: 0;
background: none;
outline: none;
}
[data-to].active:before{
opacity: 0;
}
[data-to]:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: .375rem;
height: .375rem;
margin-top: -.1875rem;
margin-left: -.1875rem;
border-radius: 50%;
background-color: var(--bs-indigo);
transition: .2s ease-in-out;
}
[data-to]:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: .75rem;
height: .75rem;
border: .125rem solid var(--bs-indigo);
border-radius: 50%;
opacity: 0;
transform: scale(.5);
transition: .2s ease-in-out;
}
[data-to].active:after {
opacity: 1;
transform: scale(1);
}
.slider .slider-outer{
position: relative;
overflow: hidden;
}
.slider-outer .slider-inner{
display: flex;
margin-right: -30px;
cursor: grab;
cursor: -webkit-grab;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
}
.slider-inner .slider-item{
width: 50%;
flex-shrink: 0;
padding-right: 30px;
}
@media (max-width: 767.98px){
.slider-outer .slider-inner{
margin-right: 0;
}
.slider-inner .slider-item{
width: 100%;
padding-right: inherit;
}
}
.slider-item a{
display: block;
position: relative;
width: 100%;
border-radius: 1rem;
overflow: hidden;
}
.slider-item a:before {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(55,56,78,.55);
opacity: 0;
transition: opacity .3s ease-in-out;
}
.slider-item a:hover:before{
opacity: 1;
}
.slider-item a > img{
width: 100%;
}
.slider-item a > span {
display: block;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
padding: 1rem .5rem;
color: white;
font-size: .875rem;
text-align: center;
opacity: 0;
transform: translateY(0.5rem);
transition: .3s ease-in-out;
}
.slider-item a:hover > span{
transform: none;
opacity: 1;
}
JS代码
/* 滑动图 */
var dotsContainer = document.getElementsByClassName("slider-indicators")[0];
var dots = dotsContainer.getElementsByTagName("button");
var slideContainer = document.querySelector(".slider-inner");
var sliderItem = slideContainer.querySelectorAll(".slider-item");
var sliderItemNum = sliderItem.length;
var sliderItemWidth = sliderItem[0].offsetWidth;
let slideIndex = 1, moveDistant = 0, currentOffset;
let isMouseDown = false;
let isImgDrag = false;
//让第一张图片于首位
window.onload = function() {
slideContainer.style.transform = "translate3d(-" + (slideIndex * sliderItemWidth) + "px, 0, 0)";
}
//滑动
function slideByDots() {
slideContainer.style.transform = "translate3d(-" + (slideIndex * sliderItemWidth) + "px, 0, 0)";
slideContainer.style.transitionDuration= ".3s";
dotsContainer.querySelector(".active").classList.remove("active");
dots[slideIndex-1].classList.add("active");
}
function slideByDrag(index, duration = ".3s") {
currentOffset = index * sliderItemWidth;
slideContainer.style.transform = "translate3d(-" + currentOffset + "px, 0, 0)";
slideContainer.style.transitionDuration= duration;
dotsContainer.querySelector(".active").classList.remove("active");
//
if(index > dots.length){
index = 1;
}
dots[index - 1].classList.add("active");
}
//点击小点
for (let dot of dots) {
dot.addEventListener("click", function(e) {
slideIndex = parseInt(e.target.dataset.to) + 1;
slideByDots();
})
}
//鼠标拖动
slideContainer.onmousedown = function(e) {
isMouseDown = true;
moveDistant = e.clientX;
currentOffset = slideIndex * sliderItemWidth;
}
slideContainer.onmousemove = function(e) {
isImgDrag = true;
if(isMouseDown){
this.style.transform = "translate3d(-" +(currentOffset + moveDistant-e.clientX)+ "px, 0, 0)";
}
}
slideContainer.onmouseup = function(e) {
isMouseDown = false;
isImgDrag = false;
if(e.clientX - moveDistant <= 60){//next
slideIndex++;
if(slideIndex > sliderItemNum - 2){
slideIndex = 1;
slideContainer.style.transitionDuration = "0s";
slideContainer.style.transform = "translate3d(-"+ (slideIndex-1)*sliderItemWidth +"px, 0, 0)";
}
slideByDrag(slideIndex);
}else if (e.clientX - moveDistant >= 60) {//prev
slideIndex--;
if(slideIndex < 1){
slideIndex = sliderItemNum - 2;
slideContainer.style.transform = "translate3d(-"+ (slideIndex-1)*sliderItemWidth +"px, 0, 0)";
slideContainer.style.transitionDuration = "0s";
}
slideByDrag(slideIndex);
}else {
slideByDrag(slideIndex);
}
}
//禁止超链接拖拽和跳转
let slideLinks = slideContainer.querySelectorAll(".slider-item > a");
for ( let slideImg of slideLinks) {
slideImg.ondragstart = function() {
return false;
}
}
for (let slideLink of slideLinks) {
slideLink.addEventListener("click", function(e) {
if(isImgDrag){
e.preventDefault();
}
})
}