介绍
轮播图的话,当下比较流行的方式就包含了图片组和按钮组,从功能上看可以得出按钮数量===图片数量,点击按钮可以切换对应的图片,用户如果没有任何操作时会自动完成轮播效果。本文记录此效果全部使用“模块”完成。
代码
index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>轮播图实战</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="slideshow">
<!-- 图片组和按钮组全部由模块动态创建 -->
<!-- 1. 图片组 -->
<div class="imgs"></div>
<!-- 2. 按钮组 -->
<!-- 按钮组中的按钮数量,必须和图片的数量完全相同 -->
<div class="btns"></div>
</div>
<script type="module">
// 获取图片组的入口
const imgs = document.querySelector(".imgs");
// 获取按钮组的入口
const btns = document.querySelector(".btns");
/**
* 当前轮播图至少需要4个函数
* 1. 创建图片组
* 2. 创建按钮组
* 3. 创建按钮事件: 实现图片的切换
* 4. 定时轮播器: 间歇式的定时器
*/
// 导入轮播图模块: slideshow.js
import slide from "./js/slideshow.js";
console.log(slide);
window.onload = function () {
// 1. 创建图片组
slide.createImgs(imgs);
// 2. 创建按钮组
slide.createBtns(imgs, btns);
// 3. 创建按钮事件: 实现图片的切换
// 注: 这里不能用事件代理/委托
// btns.onclick = function(){}
[...btns.children].forEach(function (btn) {
btn.onclick = function () {
slide.switchImg(this, imgs);
};
});
// 4. 定时轮播器: 间歇式的定时器
/**
* 首尾相连的数组(队列)
* 0,1,2
* 1,2,0
* 2,0,1
* 0,1,2
*/
//取按钮的对象转为数组
// const btnsArr = [...btns.children]
// console.log(btnsArr)
// Object.keys(): 返回对象索引组成的数组
// console.log(Object.keys({ a: 1, b: 2, c: 3 }));
// console.log(Object.keys([1, 5, 30, 222]));
// console.log(Object.keys(btnsArr))
// 间歇式定时器,第2秒换一张图片
setInterval(
function (btnsArr, btnKeys) {
console.log(btnsArr);
console.log(btnKeys);
slide.timePlay(btnsArr, btnKeys);
},
2000,
// 后面两个参数是传递给回调函数的参数,这边是按钮组对象和按钮组索引组成的数组
[...btns.children],
Object.keys([...btns.children])
);
};
</script>
</body>
</html>
style.css:
body {
background-color: #eee;
}
/* 轮播图容器 */
.slideshow {
width: 240px;
height: 360px;
/* em / rem */
}
/* 图片容器 */
.slideshow .imgs {
/* inherit从父元素获取值 */
width: inherit;
height: inherit;
/* width: 100%;
height: 100%; */
}
/* 图片适应 */
.slideshow img {
width: 100%;
height: 100%;
border-radius: 10px;
/* ? 默认全隐藏 */
display: none;
}
/* 设置图片的激活状态 */
.slideshow img.active {
display: block;
}
.slideshow img:hover {
cursor: pointer;
}
/* ------ 按钮容器 ------- */
/* 按钮容器 */
.slideshow .btns {
display: flex;
place-content: center;
position: relative;
top: -40px;
/* transform: translateY(-40px); */
}
.slideshow .btns > span {
background-color: rgba(233, 233, 233, 0.8);
height: 16px;
width: 16px;
border-radius: 50%;
margin: 5px;
}
.slideshow .btns > span.active {
background-color: orangered;
}
.slideshow .btns > span:hover {
cursor: pointer;
}
slideshow.js:
// 轮播图的功能模块
// 导入图片组的数据(图片信息)
import imgArr from "./data.js";
/**
* 当前轮播图至少需要4个函数
* 1. 创建图片组
* 2. 创建按钮组
* 3. 创建按钮事件: 实现图片的切换
* 4. 定时轮播器: 间歇式的定时器
*/
/**
* @desc 创建图片组
* @param {DOMElement} imgs - 图片容器
*/
function createImgs(imgs) {
// 使用文档片断来优化,将图片的生成与挂载放在内存中完成,以减少页面渲染和抖动
// 创建文档片断对象
const frag = new DocumentFragment();
for (let i = 0; i < imgArr.length; i++) {
// 1. 创建图片元素<img>
const img = document.createElement("img");
console.log(i, img);
// 2. 为图片添加 src, data-key自定义属性
img.src = imgArr[i].src;
img.dataset.key = imgArr[i].key;
// 3. 默认显示第一张: class='active'
if (i === 0) img.classList.add("active");
// 4. 为<img>添加click事件,跳转地址,属性是href
img.onclick = () => (location.href = imgArr[i].url);
// 5. 将<img>添加文档片断中
frag.append(img);
}
// 将<img>添加到:图片容器中
imgs.append(frag);
}
// ======================================
/**
* @desc 创建按钮组
* @param {DOMElement} imgs - 图片容器
* @param {DOMElement} btns - 按钮容器
*/
function createBtns(imgs, btns) {
// 1. 获取到图片的数量
let length = imgs.childElementCount;
// 2. 根据图片的数量生成对应的按钮
// 创建文档片断对象
const frag = new DocumentFragment();
for (let i = 0; i < length; i++) {
const span = document.createElement("span");
// 添加data-key 实现与图片的data-key的联动(绑定)
span.dataset.key = imgs.children[i].dataset.key;
if (i === 0) span.classList.add("active");
frag.append(span);
}
btns.append(frag);
}
// =======================================
/**
* @desc 创建按钮事件: 实现图片的切换
* @param {DOMElement} btn - 当前按钮
* @param {DOMElement} imgs - 图片容器
*/
function switchImg(btn, imgs) {
// 1. 去掉所有按钮和图片的"激活"状态active
[...btn.parentNode.children].forEach((btn) => btn.classList.remove("active"));
[...imgs.children].forEach((img) => img.classList.remove("active"));
// 2. 将当前用户正在点击的按钮设置为激活active
btn.classList.add("active");
// 3. 根据当前按钮的key,找到对应的图片
// btn.dataset.key ==> img.dataset.key
// 获取当前应该显示的图片
const currImg = [...imgs.children].find(
(img) => img.dataset.key === btn.dataset.key
);
// console.log(currImg);
// 4. 把这个图片设置为激活active(显示出来)
currImg.classList.add("active");
}
// ========================================
/**
* @desc 定时轮播器: 间歇式的定时器
* @param {DOMElement} btnsArr - 按钮数组(用来绑定事件)
* @param {DOMElement} btnKeys - 按钮的键构成的数组
*/
function timePlay(btnsArr, btnKeys) {
// 定时器 + 事件派发
// setInterval + dispatchEvent
// 1. 从头部取一个
let key = btnKeys.shift();
// 2. 根据索引,从按钮组中找到与该索引对应的按钮,给它自动派发一个点击事件
btnsArr[key].dispatchEvent(new MouseEvent("click"));
// 3. 将刚才取出的按钮,再次从尾部添加到按钮数组中,实现首尾相边的效果
btnKeys.push(key);
}
// ========================================
// 默认导出
export default {
createImgs,
createBtns,
switchImg,
timePlay,
};
本文地址:https://www.mainblog.cn/332.html
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
黔ICP备19006353号-2
贵公网安备 52052102000042号