为了防止自己js忘光光,准备开启小项目给自己练练手,如果有前端学习的小伙伴看到好的项目欢迎和我分享鸭🤩🤩🤩🤩
🧩轮播图🧩
html没有什么可说的,千人千结构;css的话我写了两遍之后找到的点是我们的好(老)朋友flex布局,以及如何置于顶层;重点还是我们的主角js
CSS
一、flex+position实现居中
💡Tips:这里的下标圆点外宽的div是没有设置的全都是靠着里面每一个小圆点撑起来的,这个时候有两种方法(可想而知还是我习惯性的父亲+width简洁点)
Ⅰ给dot设置宽度,并用flex中的justify-content:center,进行居中
Ⅱ不给dot设置宽度,用定位来进行让左边距和右边距都为0,再加上flex布局 justify-content:center
二、置于顶层
💡Tips:轮播图那就是有一些图片他是隐藏起来的,一开始只展示第一张后面利用样式的转移达到一张一张的播放
①让图片都叠在一起
则需要设置定位position,让图片所在的<li>和项目最外层定位,就只能显示第一张
②只展示当前页,其他隐藏
给ul中的<li>们其中一个添加不一样的样式,让他们保持显示并且至于第一层,而其他的则隐藏。css隐藏除了能用display:none之外,还可以调节图片的透明度opacity:0
把至于第一层要展示的设置为:
z-index: 1; //一层
opacity: 1; //透明度1为显示
JS
我就按照我写代码的步骤进行编写
一、让图片可以自行跳转
💡Tips:①会想到的就是js中的定时器,在设定的时间范围对图片进行切换;②切换图片是对样式进行切换,也就是排他思想,“移除自己,造福他人”
那么我们首先要拿到两个元素,当前展示的图片是who?该图片的下一张图片又是who?获取到两个元素问题就可迎刃而解啦
setTimeout(function auto() {
// ①获取当前元素
const current = document.querySelector(".list .current")
// ③获取下一个元素,若当前元素为最后一张则返回第一张
const next = current.nextElementSibling || lis[0]
// ④移除自己,添加他人
current.classList.remove("current")
next.classList.add("current")
// 再次用定时器实现循环变化
setTimeout(auto, 2000)
}, 2000)
二、添加左右按钮
💡Tips:①使用字体图标进行展示;②绑定点击事件
要清楚的是当我们点击字体图标的时候,会展示上一张或则是下一张,那么就要对应的获得:当前展示的是who?该图的上下张又是who?获取到这三个元素之后问题也就迎刃而解啦
//下一张按键
next.onclick = () => {
// ①获取当前元素
const current = document.querySelector(".list .current")
// ③获取下一个元素,当前为最后一张则返回lis的第一张
const next = current.nextElementSibling || lis[0]
// ④移除自己,添加他人
current.classList.remove("current")
next.classList.add("current")
}
//上一张按键
pre.onclick = () => {
// ①获取当前元素
const current = document.querySelector(".list .current")
// ③获取上一个元素,当前为第一张时则返回lis中的最后一张
const pre = current.previousElementSibling || lis.at(-1)
// ④移除自己,添加他人
current.classList.remove("current")
pre.classList.add("current")
}
ok写到这里你是不是觉得可以啦,接下来你就会发现以下需要我们解决的两个大难题👇
三、解决两大问题
💡Tips:Ⅰ简化代码:你会发现上述的代码中出现了超级多重复,特别时‘ next ’和‘ 图片自动播放 ’ 简直一模一样,可以用一个函数来进行包装
①找不同,pre和next差异在他们一个获取上一张一个获取下一张
②两种情况可分别用if来进行判断
//设置一个参数进行判断时pre还是next
let par;
function change(par) {
const current = document.querySelector(".list .current")
// 不同点if判断
if (par === "next") {
par = current.nextElementSibling || lis[0]
} else if (par === "pre") {
par = current.previousElementSibling || lis.at(-1)
}
// 相同
current.classList.remove("current")
par.classList.add("current")
// 记得调用函数+传参!!!
}
setTimeout(function auto() {
change("next")
setTimeout(auto, 2000)
}, 2000)
//按键调用函数并进行传参
next.onclick = () => {
change("next")
}
pre.onclick = () => {
change("pre")
}
💡Tips:Ⅱ点击上下页,定时器停止:你会发现上述的代码执行出现你点击上一页他有很快跳回去原来的图片,感觉好像卡了一样,其实是当你在点击按钮时定时器还是在进行执行ing
①创建一个定时器开关函数
②if判断开启定时器的条件
这里会存在一个误区就是老想着点击按钮才停止定时器(因为我自己也是这样),但是可以到各大网页去看当你鼠标一移入图片,轮播图就不再动了,③给整个<div>来一个鼠标事件
let timer = null
const changeTimer = () => {
// ②判断开启的条件
if (timer === null) {
// 如果timer为null证明没有开启定时器,那就开启
timer = setTimeout(function auto() {
change("next")
// 循环变化
timer = setTimeout(auto, 2000)
}, 2000)
} else {
// 开启了那么我们就关闭,并且重新赋值
clearTimeout(timer)
timer = null
}
}
// 奇数次调用函数就是开启定时器,偶数次调用函数就是关闭定时器
// 一开始就调用是实现自动播放
changeTimer()
//外层div绑定鼠标移动事件
outer.onmouseenter = () => {
changeTimer()
}
outer.onmouseleave = () => {
changeTimer()
}
四、小圆点
💡Tips:解决了上面两问题之后就来到最后一个关键的步骤下标小圆点的实现
Ⅰ开始肯定是绑定小圆点的点击事件,但是如果按平常一个个的进行绑定我们就要用到循环+绑定,有点小小的费事,何不直接用⭐事件委托,把小圆点的点击事件委托给他的父级<div>
Ⅱ点击哪个圆点展示对应图片:①当前点击的是witch小圆点?②小圆点对应的图片又是who?能让圆点和图片产生关系的只有索引号index,想找对应的索引值一定要想到⭐数组的方法indexOf()
Ⅲ 哪个图片展示对应的小圆点样式添加(active排他)
dot.addEventListener("click", (e) => {
//拿到点击小圆点的索引号
const index = dots.indexOf(e.target)
if (index != -1) {
const current = document.querySelector(".list .current")
current.classList.remove("current")
lis[index].classList.add("current")
// 修改active样式
const active = document.querySelector(".active")
active.classList.remove("active")
e.target.classList.add("active")
}
})
Ⅳ 简化代码:到这里你可能又发现了重复的代码 同样是当前页remove再add,证明也是可以加入到我们一开始为pre和next设置的简化函数change()中,只不过这次我们传入的参数是index,不是字符串
let par;
function change(par) {
const current = document.querySelector(".list .current")
// 不同点if判断
if (par === "next") {
par = current.nextElementSibling || lis[0]
} else if (par === "pre") {
par = current.previousElementSibling || lis.at(-1)
} else {
// 如果active的切换放在里面的话,就没办法跟随图片动
//拿到lis图片数组中和小圆点对应索引号的图片赋值
par = lis[par]
}
// 相同
current.classList.remove("current")
par.classList.add("current")
/*
如果放在外面的话就要重新考虑下选择的index是谁???
→ index = 点击圆点/变化后图片的索引
→ 变化后的图片为赋值后的par
→ 用lis数组判断(indexOf)上述par的索引号是多少
*/
//找到被赋值后par再lis图片数组中的索引号是多少?给dot来进行active样式的切换
const index = lis.indexOf(par)
const active = document.querySelector(".active")
active.classList.remove("active")
dots[index].classList.add("active")
// 记得调用函数+传参!!!
}
dot.addEventListener("click", (e) => {
const index = dots.indexOf(e.target)
console.log(index);
if (index != -1) {
//传入当前点击的小圆点索引号
change(index)
}
})