原生JS实现自动无缝切换轮播图(可鼠标拖动)

^ _ ^ 最近参加了一个免费的华为在线课程,有一个作业是用原生js实现轮播图。练手的同时发现工作中框架用的多。原生JS不如以前那么熟练了。特此写这篇文章记录一下。希望能帮助到一些新手盆友。来一起学习吧。

功能需求

实现以下4个需求:

  1. 自动无缝切换图片
    自动无缝切换图片

  2. 鼠标左右拖动切换图片
    鼠标左右拖动切换图片

  3. 点击小点切换对应图片
    点击小点切换对应图片

  4. 浏览器窗口尺寸改变不影响以上功能

实现思路

html & CSS结构分析

  1. 清除浏览器默认样式和设置基础样式
*{
   
	box-sizing: border-box;
}
body, ul{
   
	margin: 0;
	padding: 0;
	font-family: PingFang SC,PingFangSC-Regular,Helvetica Neue,Microsoft YaHei Regular,Microsoft YaHei,宋体,"sans-serif";
	font-size: 16px;
}
  1. 设置一个外层容器
<div class= page”>
.page{
   
	overflow: hidden; //让视线范围内只显示一张图片
	position: relative; //用于点的定位
}
  1. 设置一个内层容器
<div class=”box”>
.box{
   
	display: flex; //设置flex布局,默认从左到右依次排列。
}

不清楚flex的盆友可以看一下阮大神的文章:Flex 布局教程:语法篇

  1. 设置一个包住a链接和img图片的容器
<div class="slideWrapper"> <a href="xxx" target="_blank"><img class="slide" src="xxx.jpg "</a></div>
.slideWrapper{
   
	width: 100%;
   	height: 100%;
   	flex-shrink: 0;
}

需要注意的是除了需要设置宽高100%以外,还有设置flex-shrink: 0; 不让容器等比例缩小

  1. 设置点击小点的样式
.dots{
   
	position: absolute;
	bottom: 45px;
	left: 50%;
	transform: translateX(-50%);
}
.dots span{
   
	margin: 0 4px;
	width: 8px;
	height: 8px;
	display: inline-block;
	border-radius: 100%;
	background: #000;
	opacity: .2;
	text-indent: -9999px;
}
span.active {
   
	width: 28px!important;
	background: #5e7ce0!important;
	border-radius: 5px!important;
	opacity: 1;
}

JS逻辑实现

自动无缝切换

第一步、创建函数,通过修改内层容器“box” 的transform: translateX(?px)来切换显示图片。

let boxDom = document.querySelector('.box');
function changeBoxDomStyle(offset, duration = '0ms') {
   
	boxDom.style.transform = `translateX(${
     offset}px)`;
	boxDom.style.transitionDuration = duration;
}

第二步、计算当前所需偏移量,并调用设置偏移量函数carousel ,调用设置小点激活状态函数changeDotsStyle

技巧

  • 每一次的偏移量就是图片宽度 * 索引 moveWith * index
  • 表面上8张图片,实际上是 8副本 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 1副本 排序,索引是0 - 9. 总共10张图片。当index = 9 也就是切换到第一张图片副本的时候,迅速切换到真正的第一张图片。因为没有动画时间,所以用户感受不到切换。
    注意一定要放到 boxDom.addEventListener('transitionend', () => {})才能保证从8 -> 1副本能够顺利执行完了,再无痕迹的切换到真正的第一张图片。至于不放在这里面直接在赋值新的style会出什么副作用,就动手试试吧。
  • 转换图片的同时,也要把对应索引的小点的样式设置成active的样式
let index = 1;
let imgLen = document.querySelectorAll('.slide').length;
let moveWith = document.querySelector('.slide').offsetWidth;
let currentOffset =  moveWith;
const DEFAULT_DURATION = '300ms';
function carousel() {
   
	//当切换到1副本的时候,迅速切换到真正的第一张图片
	boxDom.addEventListener('transitionend', () => {
   
		if(index === imgLen - 1){
   
			index = 1;
			currentOffset = moveWith;
			changeBoxDomStyle(-currentOffset);
		}
	});
	//
	if(index < imgLen - 1){
   
		index++;
		changeDotsStyle();
		currentOffset = moveWith * index;
		changeBoxDomStyle(-currentOffset, DEFAULT_DURATION);
	}
}

function changeDotsStyle() {
   
		document.querySelector('.dot_item.active').classList.remove('active');
		if(index === imgLen - 1){
   
			dotItems[0].classList.add('active');
		}else{
   
			dotItems[index - 1].classList.add('active');
		}
	}

第三步、创建定时器调用函数carousel

const ANIMATION_INTERVAL = 3000;
function autoPlay() {
   
	if(isAutoPlay){
    return; }
	isAutoPlay = true;
	animate = setInterval(carousel, ANIMATION_INTERVAL);
}

点击小点切换对应图片

给每个小点绑定点击事件,获取当前的索引,调用设置偏移量函数carousel。
注: 别忘了先停止定时器,再重起定时器

function dotsControl() {
   
	for(dot of dotItems){
   
		dot.addEventListener("click", (e) => {
   
			stopAutoPlay();
			index = e.target.getAttribute('data-dots-index') - 1;
			carousel();
			autoPlay();
		});
	}	
}
function stopAutoPlay() {
   
	if(!isAutoPlay){
    return; }
	isAutoPlay = false;
	clearInterval(animate);
}

鼠标拖动切换图片

这是需求里面最难的。涉及多个鼠标事件,还有一个小坑
第一步、鼠标按下时,停止定时器。获取当前的X坐标currentX, 修改isKeyDown 为true。

let isKeyDown = false;
boxDom.addEventListener('mousedown', (e) => {
   
	stopAutoPlay();
	isKeyDown = true;
	isDragingImg = false;
	currentX = e.clientX;
})
  • 20
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值