Js原生轮播图切出切面一段时间再回来,轮播动画混乱问题

这个问题是早前自己玩轮播图时遇到的,查了些资料,但大多都对不上我的问题,最后在知知乎乎那里看到了解释。解释是这样说的:

页面切走,有的浏览器会正常走定时器,正常更新排版视图。有的则放慢定时器,停止排版视图更新,甚至有插电和不插电的笔记本是否进入节能模式,浏览器为了节能,其优化策略都会产生调整,比如定时器精度变化.。如果代码没考虑到这些问题,可能会出岔子,个人建议,你的动画体系要以帧为主要核心。而不是以时间,见过市面上大多数动画库都错误的把时间作为缓动核心...

可以按照第一句解释来看,就出在浏览器对定时器的安排上了,有的浏览器看着你在它面前,它就好好给你走定时器,你一不看它去看别的页面了,它就偷懒不走或放慢定时器了,当咱们再回来的时候,它发现咱回来看它了,它就把堆积的定时器一统一块执行了,好家伙,这能不乱吗。

硬核解决方案就是监测咱看没看它

// 回来到当前页面,清除残留定时器的影响,执行定时器
window.onfocus=function(){
	clearInterval(timer)
	timer=setInterval(function(){
        button_right.click()
	},2000)
}
// 离开当前页面清除定时器,避免定时器生成堆积
window.onblur=function(){
	clearInterval(timer);
}

li,i,ul{
	list-style: none;
	margin: 0;
	padding: 0;
}
.swiper{
	margin: 100px auto;
	overflow: hidden;
	width: 1226px;
	height: 460px;
	position: relative;
}
.swiper ul{
	position: absolute;
	top: 0;
	left: 0;
	height: 460px;
	width: 600%;
}
.swiper ul li{
	width: 1226px;
	height: 460px;
	float: left;
}
.swiper img{
	display: block;
	width: 100%;
	height: 100%;
}
/* 左右按钮 */
.swiper span{
	font-size: 25px;
	display: block;
	width: 50px;
	height: 50px;
	line-height: 50px;
	text-align: center;
	color: #ccc;
	margin-top: -25px;
	position: absolute;
	top: 50%;
	/* 先隐藏,在鼠标进入轮播图区域的时候显示 */
	display: none;
	cursor: pointer;
}
.swiper .button-right{
	right: 0;
}
.swiper .button-left{
	left: 0;
}
.swiper span:hover{
	background-color: #e0e0e0;
	color: black;
}
/* 小圆圈 */
.bullets{
	position: absolute;
	bottom: 30px;
	right: 60px;
	width: 300px;
	height: 20px;
	text-align: right;
}
.bullets i{
	display: inline-block;
	height: 10px;
	width: 10px;
	border: 3px solid #cccccc;
	background-color: #e0e0e0;
	border-radius: 50%;
	margin: 0 3px;
}
.bullets .active{
	background-color: #FF7F50;
}
<div class="swiper">
	<!-- 轮播的图片 -->
	<ul></ul>
	<!-- 左右按钮 -->
	<span class="button-left">&lt;</span>
	<span class="button-right">&gt;</span>
	<!-- 小圆圈 -->
	<div class="bullets"></div>
</div>
// 定义一些中间值
let num=0//记录图片滚动,滚动一次就+1,或者点击小圈变到相应的index
let circle=0//记录小圈变化,滚动一次就+1,或者点击变到相应的index
let timer=null;
// 获取元素
let swiper=document.querySelector('.swiper')
let ul=document.querySelector('.swiper ul')
let bullets=document.querySelector('.bullets')
let button_left=document.querySelector('.button-left')
let button_right=document.querySelector('.button-right')

// 动态添加图片和小圈
let arr=['./images/slider(1).jpg', './images/slider(2).jpg', './images/slider(3).jpg', './images/slider(4).jpg',
	'./images/slider(5).jpg']
let html=''
for(let i=0;i<arr.length;i++){
	html+='<li><a><img src='+arr[i]+'></img></a></li>'
	// 这里生成小圈
	let ii=document.createElement('i')
	ii.setAttribute('index',i)
	bullets.appendChild(ii)
}
ul.innerHTML=html

// 克隆第一张图片放到最后这是为了实现无缝滚动效果
let last_li=ul.children[0].cloneNode(true)
ul.appendChild(last_li)
// 默认第一个小圈是active
bullets.children[0].className='active'
// 追加完克隆元素之后再重新赋值下,避免下文走ul.children把ul当作初始的无children的节点
ul=document.querySelector('.swiper ul')

// 控制左右按钮的显示与隐藏
swiper.addEventListener('mouseenter',function(){
	button_left.style.display="block"
	button_right.style.display="block"
	// 鼠标进入的时候,不轮播
	clearInterval(timer)
	timer=null
})
swiper.addEventListener('mouseleave',function(){
	button_left.style.display="none"
	button_right.style.display="none"
	// 出去的时候继续轮播
	timer=setInterval(function(){
		button_right.click()
	},2000)
})

// 点击右边按钮
button_right.addEventListener('click',function(){
	// 如果到了最后一张图片,就立马回到一开始的第一张,这两张图片一样
	if(num==ul.children.length-1){
		num=0
		ul.style.transition='none'
		ul.style.transform='translateX('+swiper.offsetWidth*-num+'px)'
		// 改变了之后必须得重绘,不然没效果(过渡就会被后面的盖过)
	}
	num++
	// 小圈改变
	circle++
	ul.style.transition='all 1s ease'
	ul.style.transform='translateX('+swiper.offsetWidth*-num+'px)'
	if(circle==bullets.children.length) circle=0
	circleChange()
})

// 点击左边的按钮
button_left.addEventListener('click',function(){
	// 和右移差不多
	if(num==0){
		num=ul.children.length-1
		ul.style.transition='all 0s'
		ul.style.transform='translateX('+swiper.offsetWidth*-num+'px)'
		// 改变了之后必须得重绘,不然没效果(过渡就会被后面的盖过)
	}
	num--
	ul.style.transition='all 1s ease'
	ul.style.transform='translateX('+swiper.offsetWidth*-num+'px)'
	// 小圈改变
	circle--
	if(circle<0) circle=bullets.children.length-1
	circleChange()
})


// 老关键了这一步,动画结束后就开始判断当前的num
// 否则会出现index=5的之后直接translateX越过0px变为-1*swiper.offsetWidth px
ul.addEventListener("transitionend",() => {
	  if(num > 4) {
		num = 0
		ul.style.transition = "none";// 将动画置空,否则下面这个translateX的设置会触发动画变换到0px的位置,而不是瞬移
		ul.style.transform = 'translateX('+swiper.offsetWidth*-num+'px)';
	  }
},false)

// 点击小圈的时候也可以控制播放(这里可以在生成小圈的时候直接加监听,也可以在这里)
for(let i=0;i<bullets.children.length;i++){
	bullets.children[i].addEventListener('click',function(){
		// 得到小圈的index
		circle=this.getAttribute('index')
		// 调用下面定义好的函数
		circleChange()
		num=circle
		ul.style.transform='translateX('+swiper.offsetWidth*-num+'px)'
	})
}

// 小圈的改变
function circleChange(){
	for(let i=0;i<bullets.children.length;i++){
		bullets.children[i].className=''
	}
	bullets.children[circle].className='active'
}
// 自动轮播
timer=setInterval(function(){
	button_right.click()
},2000)

// 避免页面切换动画累积影响效果
window.onfocus=function(){
	clearInterval(timer)
	timer=setInterval(function(){
		button_right.click()
	},2000)
}
window.onblur=function(){
	clearInterval(timer);
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个简单的原生JavaScript实现轮播图的代码: HTML部分: ```html <div class="slider"> <div class="slider-container"> <img src="image1.jpg"> <img src="image2.jpg"> <img src="image3.jpg"> </div> <div class="slider-prev">❮</div> <div class="slider-next">❯</div> <div class="slider-dots"> <span class="slider-dot"></span> <span class="slider-dot"></span> <span class="slider-dot"></span> </div> </div> ``` CSS部分: ```css .slider { position: relative; } .slider-container { display: flex; width: 100%; height: 100%; overflow: hidden; } .slider-container img { width: 100%; height: 100%; object-fit: cover; } .slider-prev, .slider-next { position: absolute; top: 50%; transform: translateY(-50%); z-index: 1; cursor: pointer; font-size: 30px; color: white; user-select: none; } .slider-prev { left: 0; } .slider-next { right: 0; } .slider-dots { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); z-index: 1; } .slider-dot { display: inline-block; width: 8px; height: 8px; margin-right: 5px; background-color: gray; border-radius: 50%; cursor: pointer; } .slider-dot.active { background-color: white; } ``` JavaScript部分: ```javascript const sliderContainer = document.querySelector('.slider-container'); const slides = sliderContainer.querySelectorAll('img'); const prevBtn = document.querySelector('.slider-prev'); const nextBtn = document.querySelector('.slider-next'); const dotsContainer = document.querySelector('.slider-dots'); const dots = dotsContainer.querySelectorAll('.slider-dot'); let slideIndex = 0; // 设置轮播图的初始状态,显示第一张图片 slides[slideIndex].style.display = 'block'; dots[slideIndex].classList.add('active'); // 点击下一张按钮,切换到下一张图片 nextBtn.addEventListener('click', () => { slides[slideIndex].style.display = 'none'; dots[slideIndex].classList.remove('active'); slideIndex++; if (slideIndex >= slides.length) { slideIndex = 0; } slides[slideIndex].style.display = 'block'; dots[slideIndex].classList.add('active'); }); // 点击上一张按钮,切换到上一张图片 prevBtn.addEventListener('click', () => { slides[slideIndex].style.display = 'none'; dots[slideIndex].classList.remove('active'); slideIndex--; if (slideIndex < 0) { slideIndex = slides.length - 1; } slides[slideIndex].style.display = 'block'; dots[slideIndex].classList.add('active'); }); // 点击圆点按钮,切换到对应的图片 dotsContainer.addEventListener('click', e => { const dot = e.target.closest('.slider-dot'); if (dot) { slides[slideIndex].style.display = 'none'; dots[slideIndex].classList.remove('active'); slideIndex = Array.from(dots).indexOf(dot); slides[slideIndex].style.display = 'block'; dots[slideIndex].classList.add('active'); } }); // 自动轮播,每5秒切换到下一张图片 setInterval(() => { nextBtn.click(); }, 5000); ``` 以上是一个基本的轮播图的实现,您可以根据需求进行修改和定制,希望能够帮助到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值