JS轮播图

轮播图基础

  • 巩固完JavaScriptDOM自己尝试写一下轮播图
小功能
  • 上一页、下一页
  • 自动轮播
  • 鼠标悬停止轮播
  • 点击小方框轮播
  • 无缝轮播
涉及知识点
  • JS面向对象Class
  • JSDOM操作
  • this指向
  • 事件委托
  • 事件监听
  • 动画封装
  • 定时器
  • 节流阀
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>轮播图</title>
	</head>
	<body>
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
				box-sizing: border-box;
			}

			#slideshow {
				margin: 60px 60px 0 60px;
				width: 1000px;
				position: relative;
			}

			li {
				list-style: none;
			}

			.continer {
				width: 1000px;
				overflow: hidden;
			}

			.continer ul {
				width: 1000px;

				display: flex;
			}

			.continer ul li {
				width: 100%;
				height: 100%;
			}

			.continer ul li img {
				width: 1000px;
				height: 640px;
				cursor: pointer;
			}

			.labels {
				position: absolute;
				top: 90%;
				left: 50%;
				transform: translate(-50%, -50%);
			}

			.labels ul {
				display: flex;
			}

			.labels ul li {
				width: 30px;
				display: flex;
				justify-content: center;
				align-items: center;
			}

			.labels ul li span {
				display: inline-block;
				width: 15px;
				height: 15px;

				background: #fff;
			}

			.active {
				background: red !important;
				width: 30px;
			}

			.arrows {
				width: 100%;
				height: 60px;
				display: flex;
				justify-content: space-between;
				align-items: center;
				position: absolute;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
			}

			.circl {
				width: 60px;
				height: 60px;
				border-radius: 50%;
				background: rgb(0, 0, 0, .2);
				position: relative;
				overflow: hidden;
				cursor: pointer;
				/* display: none; */
			}

			.circl .square {
				width: 60px;
				height: 60px;
				border-left: 3px solid #999999;
				border-bottom: 3px solid #999999;
				position: absolute;
				top: 50%;
				left: 100%;
				transform: translate(-50%, -50%) rotate(45deg);
			}

			.circl .square.right {
				top: 50%;
				left: 0%;
				border-top: 3px solid #999999;
				transform: translate(-50%, -50%) rotate(135deg);
			}
		</style>
		<div id="slideshow">
			<div class="continer">
				<ul>
				</ul>
			</div>
			<div class="labels">
				<ul>
				</ul>
			</div>
			<div class="arrows">
				<div class="circl left">
					<div class="square ">

					</div>
				</div>
				<div class="circl right">
					<div class="square right">

					</div>
				</div>
			</div>
		</div>

		<script type="text/javascript">
			let imgArr = ["./img/1.jpg", "./img/2.jpg", "./img/3.jpg", "./img/4.jpg"]
			let that;
			class Slideshow {
				constructor(name) {
					that = this
					this.continer = document.querySelector('.continer')
					this.labels = document.querySelector('.labels')
					this.arrowsLeft = document.querySelector('.left')
					this.arrowsRight = document.querySelector('.right')

					this.init()
					this.getAll()
					this.currentCarouselIndex = 0 // 当前循环被激活的下标
					this.carouselTimer = null //循环的定时器开关
					this.autoCarousel() // 开启循环
					// this.stopCarousel() // 关闭循环轮播
					this.flag = true // 节流阀 
				}
				getAll() {
					this.lis = this.labels.querySelectorAll('li')
					this.imgs = this.continer.querySelectorAll('ul li img')
					this.lis[0].children[0].className += ' active'
					this.labels.children[0].addEventListener('click', that.hadellabelClick)
				}
				init() {
					// 动态初始化轮播图 img 和 小圆点
					that = this
					let str = [];
					let labelStr = []
					imgArr.forEach((item, index) => {
						str.push(`<li><img data-index=${index} src="${item}" ></li>`)
						labelStr.push(`<li data-index=${index}><span></span></li>`)
					})
					that.continer.children[0].innerHTML = str.join('')
					that.labels.children[0].innerHTML = labelStr.join('')
					that.continer.children[0].appendChild(that.continer.children[0].children[0].cloneNode(true))
					// 绑定鼠标移入和移除事件
					this.continer.children[0].addEventListener('mouseover', this.handelMouseenter)
					this.continer.children[0].addEventListener('mouseout', this.handelMouseleave)
					// 箭头事件
					this.arrowsLeft.addEventListener('click', this.handelArrowsLef)
					this.arrowsRight.addEventListener('click', this.handelArrowsRight)
							this.arrowsLeft.parentNode.addEventListener('mouseover', this.handelMouseenter)
				}
				hadellabelClick(e) {
					that.flag = false
					clearInterval(that.carouselTimer)
					// 拿到当前点击事件的 index下标值 由于html层级结构设计的不是很好只能这样了(事件委托)
					const index = e.target.getAttribute('data-index') ? e.target.getAttribute('data-index') : e.target
						.parentNode.getAttribute('data-index')
					// 排他思想 先清除所有后添加
					that.cancelActiveClass()
					that.labels.children[0].children[index].children[0]?.classList.add('active')
					// 更新当前的坐标
					that.currentCarouselIndex = index
					//开启移处理动事件 
					that.hadelOffset(that.currentCarouselIndex)

				}
				// 清除所有的class
				cancelActiveClass() {
					Array.from(that.labels.children[0].children).forEach(item => {
						item.children[0].classList?.remove('active')
					})
				}
				// 得到当前点击事件的index 并计算移动距离
				hadelOffset(index) {
					// 如果当前开启了自动轮播 先暂停自动轮播
					clearInterval(that.carouselTimer)
					const ul = this.continer.children[0]
					if (index >= imgArr.length) {
						that.cancelActiveClass()
						that.labels.children[0].children[0].children[0]?.classList.add('active')
						animate(ul, -ul.offsetWidth * imgArr.length, 10, 30, function() {
							ul.style.marginLeft = 0
							that.currentCarouselIndex = 0
							that.flag = true
						})
					} else if (index <= 0) {
						that.cancelActiveClass()
						that.labels.children[0].children[0].children[0]?.classList.add('active')
						animate(ul, -ul.offsetWidth * index, 10, 30, function() {
							ul.style.marginLeft = -(ul.children.length - 1) * ul.offsetWidth + 'px'
							that.currentCarouselIndex = ul.children.length - 1
							that.flag = true
						})
					} else {
						animate(ul, -ul.offsetWidth * that.currentCarouselIndex, 10, 30, function() {
							that.autoCarousel(that.currentCarouselIndex)
							that.flag = true
						})
						that.cancelActiveClass()
						that.labels.children[0].children[that.currentCarouselIndex].children[0]?.classList.add('active')
					}
				}
				// 自动轮播
				autoCarousel(currentCarouselIndex) {
					const ul = this.continer.children[0]
					that.currentCarouselIndex = currentCarouselIndex ? currentCarouselIndex : 0
					if (that.carouselTimer) clearInterval(that.carouselTimer)
					that.carouselTimer = setInterval(() => {
						that.currentCarouselIndex > imgArr.length ? that.currentCarouselIndex = 0 : that
							.currentCarouselIndex++
						if (that.currentCarouselIndex >= imgArr.length) {
							that.cancelActiveClass()
							that.labels.children[0].children[0].children[0]?.classList.add('active')
							animate(ul, -ul.offsetWidth * imgArr.length, 10, 30, function() {
								ul.style.marginLeft = 0
								that.currentCarouselIndex = 0
							})
						} else {
							animate(ul, -ul.offsetWidth * that.currentCarouselIndex, 10, 30)
							that.cancelActiveClass()
							that.labels.children[0].children[that.currentCarouselIndex].children[0]?.classList.add(
								'active')
						}
					}, 2000)

				}
				// 停止轮播
				stopCarousel() {
					if (that.carouselTimer)
						clearInterval(that.carouselTimer)
				}
				// 鼠标移入停止轮播
				handelMouseenter() {
					that.stopCarousel()
					// 显示箭头
					that.arrowsLeft.style.display = 'block'
					that.arrowsRight.style.display = 'block'
				}
				// 鼠标移出继续轮播
				handelMouseleave() {
					that.autoCarousel(that.currentCarouselIndex)
					that.arrowsLeft.style.display = 'none'
				 that.arrowsRight.style.display = 'none'
				}
				// 左箭头减一
				handelArrowsLef() {
					if (that.flag) {
						that.flag = false
						that.currentCarouselIndex <= 0 ? that.currentCarouselIndex = 0 : that.currentCarouselIndex--
						that.hadelOffset(that.currentCarouselIndex)
					}
				}
				// 右箭头加1
				handelArrowsRight() {
					if (that.flag) {
						that.flag = false
						that.currentCarouselIndex > imgArr.length ? that.currentCarouselIndex = 0 : that
							.currentCarouselIndex++
						that.hadelOffset(that.currentCarouselIndex)
					}
				}
			}

			new Slideshow('#slideshow')
			// 封装轮播动画函数
			function animate(obj, target, spped = 10, time, callback) {
				clearInterval(obj.timer)
				obj.timer = setInterval(() => {
					let step = (target - obj.offsetLeft) / spped
					step = step > 0 ? Math.ceil(step) : Math.floor(step)
					if (obj.offsetLeft == target) {
						clearInterval(obj.timer)
						callback?.()
					}
					obj.style.marginLeft = obj.offsetLeft + step + 'px'

				}, time)
			}
		</script>
	</body>
</html>
``
![在这里插入图片描述](https://img-blog.csdnimg.cn/ade18add0ceb4def9f6c29ad89d80d0b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA44OZ6L-c6KGM44Of,size_20,color_FFFFFF,t_70,g_se,x_16)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ベ远行ミ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值