JavaScript —— 实现一个简易版轮播图
先看看效果:
零、起因和思路
昨天有位小伙伴询问一种轮播导航栏要如何做:
今晚寻思着,刚睡醒吃完,花点时间撸一下。老样子,完整代码放最后面,具体思路如下:
- 点击某一项滚动
- 点击上一项或下一项滚动
- 自动滚动轮播
- 鼠标移入移出暂停轮播
一、设计结构
<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>