JavaScript —— 实现一个简易版轮播图

JavaScript —— 实现一个简易版轮播图

先看看效果:
效果

零、起因和思路

昨天有位小伙伴询问一种轮播导航栏要如何做:
起因

起因
今晚寻思着,刚睡醒吃完,花点时间撸一下。老样子,完整代码放最后面,具体思路如下:

  1. 点击某一项滚动
  2. 点击上一项或下一项滚动
  3. 自动滚动轮播
  4. 鼠标移入移出暂停轮播

一、设计结构

<body>
	<div class="over"></div>
</body>

样式代码:

<style>
.over {
	position: relative;
	width: 100%;
	height: 40px;
	overflow-y: hidden;
	overflow-x: scroll;
	white-space: nowrap;
	position: relative;
}
.over::-webkit-scrollbar {
	width: 0;
	height: 0;
	color: transparent;
}
.item {
	text-align: center;
	display: inline-block;
	width: 60px;
	height: 40px;
	line-height: 40px;
	font-family: monospace;
	cursor: pointer;
}
.arrow {
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	width: 30px;
	height: 40px;
	display: flex;
	justify-content: center;
	align-items: center;
	font-size: 20px;
	background-color: green;color: white;
	cursor: pointer;
}
.next {
	right: 0;
}
.pre {
	left: 0;
}
.line {
	position: absolute;
	content: '';
	display: block;
	bottom: 0;
	left: 0;
	transform: translateX(13px);
	width: 34px;
	height: 2px;
	background-color: darkgreen;
	transition: left .5s;
}
</style>

生成元素:

// 元素个数
var itemNum = 30;
(function() {
	const html = new Array()
	for(let i = 0; i < itemNum; i++) {
		const div = '<div class="item" οnclick="itemClick('+i+')">'+(i+1)+'</div>'
		html.push(div)
	}
	const next = '<div class="arrow next" οnclick="nextClick()">></div>'
	const pre = '<div class="arrow pre" οnclick="preClick()"><</div>'
	const line = '<div class="line"></div>'
	html.push(next)
	html.push(line)
	html.push(pre)
	parentScroll.innerHTML = html.join('');
})()

二、实现点击事件

// 先获取三个element
const parentScroll = document.querySelector(".over");
const childScroll = document.querySelectorAll(".item");
const lineScroll = document.querySelector(".line");
// 定义控制滚动下标
var itemIndex = 0;

// 单项点击事件
function itemClick(index) {
	// 临界值处理
	if (index == -1) {
		itemIndex = itemNum - 1
	} else if (index == itemNum) {
		itemIndex = 0
	} else {
		itemIndex = index
	}
	// 控制下划线和整体滚动
	scrollCheck(itemIndex)
}

// 上一项点击事件
function preClick() {
	itemClick(--itemIndex)
}

// 下一项点击事件
function nextClick() {
	itemClick(++itemIndex)
}

// 控制下划线滚动函数
function scrollLine(left) {
	lineScroll.style.left = left + 'px'
}

// 控制下划线和整体滚动函数
function scrollCheck(index) {
	let parentLeft = parentScroll.scrollLeft; // 获取父元素滚动条位置,用于设置整体滚动
	let parentWidth = parentScroll.clientWidth / 2; // 获取父元素可视区域中间值,用于比较
	let childLeft = childScroll[index].offsetLeft; // 获取子元素距父元素左侧距离,用于设置下划线位置
	let childScrollWidth = childScroll[index].offsetLeft + childScroll[index].clientWidth / 2; // 获取每一项中间值距父元素左侧距离,用于比较
	// 如果当前项的中间值距父元素左侧距离,比父元素可视区域中间值,小,那么整体不滚动
	// 反之,将横向滚动element.scrollLeft的值设置为当前项的中间值距父元素左侧距离,形成滚动
	if (childScrollWidth < parentWidth) {
		parentScroll.scrollTo({
			left: 0,
			behavior: "smooth"
		})
	} else {
		parentScroll.scrollTo({
			left: childScrollWidth - parentWidth + childScroll[index].clientWidth / 2,
			behavior: "smooth"
		})
	}
	// 控制下划线滚动
	scrollLine(childLeft)
}

三、实现自动轮播

var timer = null;
function autoPlay() {
	timer = setInterval(() => {
		nextClick()
	}, 2000)
}

四、实现鼠标移停

parentScroll.onmouseenter = function() {
	clearInterval(timer)
}

parentScroll.onmouseleave = function() {
	autoPlay()
}

五、完整代码

<script>
	var timer = null;
	var itemNum = 30;
	var itemIndex = 0;
	const parentScroll = document.querySelector(".over");
	
	(function() {
		const html = new Array()
		for(let i = 0; i < itemNum; i++) {
			const div = '<div class="item" οnclick="itemClick('+i+')">'+(i+1)+'</div>'
			html.push(div)
		}
		const next = '<div class="arrow next" οnclick="nextClick()">></div>'
		const pre = '<div class="arrow pre" οnclick="preClick()"><</div>'
		const line = '<div class="line"></div>'
		html.push(next)
		html.push(line)
		html.push(pre)
		parentScroll.innerHTML = html.join('');
	})()
	
	const childScroll = document.querySelectorAll(".item");
	const lineScroll = document.querySelector(".line");
	
	function itemClick(index) {
		if (index == -1) {
			itemIndex = itemNum - 1
		} else if (index == itemNum) {
			itemIndex = 0
		} else {
			itemIndex = index
		}
		scrollCheck(itemIndex)
	}
	
	function nextClick() {
		itemClick(++itemIndex)
	}
	
	function preClick() {
		itemClick(--itemIndex)
	}
	
	function scrollCheck(index) {
		let parentLeft = parentScroll.scrollLeft;
		let parentWidth = parentScroll.clientWidth / 2;
		let childLeft = childScroll[index].offsetLeft;
		let childScrollWidth = childScroll[index].offsetLeft + childScroll[index].clientWidth / 2;
		if (childScrollWidth < parentWidth) {
			parentScroll.scrollTo({
				left: 0,
				behavior: "smooth"
			})
		} else {
			parentScroll.scrollTo({
				left: childScrollWidth - parentWidth + childScroll[index].clientWidth / 2,
				behavior: "smooth"
			})
		}
		scrollLine(childLeft)
	}
	
	function scrollLine(left) {
		lineScroll.style.left = left + 'px'
	}
	
	function autoPlay() {
		timer = setInterval(() => {
			nextClick()
		}, 2000)
	}
	
	parentScroll.onmouseenter = function() {
		clearInterval(timer)
	}
	
	parentScroll.onmouseleave = function() {
		autoPlay()
	}
	
	autoPlay()
	
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值