轮播图-添加翻页-自动播放-图片懒加载
程序员文章站
2022-03-13 13:52:46
...
轮播图-添加翻页-自动播放-图片懒加载
- 为翻页按钮添加功能
- 当鼠标移出时,图片的每隔2秒的自动播放,当鼠标移入时自动停止播放
- 上节课的选项卡, 懒加载二选一
1和2轮播图,添加翻页和隔两秒自动播放
-
head
标签添加
<link rel="stylesheet" href="banner/style.css" />
- 引入的
banner/style.css
是默认的
/* 初始化 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
}
/* 轮播图的容器 */
.container {
width: 62.5em;
height: 22em;
margin: 1em auto;
/* 转为定位元素/定位父级 */
position: relative;
}
/* 图片组 */
.container > .imgs img {
width: 100%;
height: 100%;
/* 默认全部隐藏 */
display: none;
/* 将所有的图片进行绝对定位,确保每一次只看到一张,所有图片共享这个容器 */
position: absolute;
left: 0;
top: 0;
}
/* 设置默认显示的图片(第一张) */
.container > .imgs img.active {
display: block;
}
/* 按钮组(独立按钮) */
.container > .btns {
position: absolute;
left: 0;
right: 0;
bottom: 0;
/* 水平居中 */
text-align: center;
}
.container > .btns a {
/* 转成行内块元素: 即能水平排列,双支持宽度设置 */
display: inline-block;
padding: 0.5em;
margin: 0 0.2em;
background-color: #fff;
border-radius: 50%;
}
.container > .btns a.active {
background-color: #000;
}
/* 翻页按钮 */
.container .skip a {
position: absolute;
width: 2.5rem;
height: 5rem;
line-height: 5rem;
text-align: center;
opacity: 0.3;
top: 9rem;
font-weight: lighter;
font-size: 2rem;
background-color: #ccc;
}
.container .skip .prev {
left: 0;
}
.container .skip .next {
right: 0;
}
.container .skip *:hover {
opacity: 0.6;
color: #666;
}
-
body
中添加html是默认的
<div class="container">
<!-- 1. 图片组 -->
<nav class="imgs">
<a href="#"><img src="banner/banner1.jpg" alt="" data-index="0" class="active" /></a>
<a href="#"><img src="banner/banner2.jpg" alt="" data-index="1" /></a>
<a href="#"><img src="banner/banner3.jpg" alt="" data-index="2" /></a>
<a href="#"><img src="banner/banner4.jpg" alt="" data-index="3" /></a>
</nav>
<!-- 2. 图片小按钮 -->
<nav class="btns">
<!-- 这些小按钮应该根据图片数量自动生成 -->
<!-- <a href="" data-index="0" class="active"></a>
<a href="" data-index="1"></a>
<a href="" data-index="2"></a>
<a href="" data-index="3"></a> -->
</nav>
<!-- 3. 翻页 -->
<nav class="skip">
<a href="#" class="prev"><</a>
<a href="#" class="next">></a>
</nav>
</div>
- 续写 js 图片轮播
<script>
// 图片组
const imgs = document.querySelectorAll(".container > .imgs img");
// 按钮组
const btnGroup = document.querySelector(".container > .btns");
// 翻页按钮
const skip = document.querySelector(".container > .skip");
// 根据图片组imgs的图片数量向按钮组btnGroup添加图片数量个按钮
function autoCreateBtns(btnGroup, imgs) {
imgs.forEach((img, i) => {
// 创建并设置 a 标签属性
let a = document.createElement('a');
a.href = "#";
a.dataset.index = i;
// 图片处以激活时,对应的按钮也处于激活状态
if (img.classList.contains('active')) {
a.classList.add('active');
}
// 追加到父级元素
btnGroup.appendChild(a);
});
}
autoCreateBtns(btnGroup, imgs)
// 获取按钮组
const btns = document.querySelectorAll(".container > .btns > *");
// 获取激活的元素(图片|按钮)
function getActiveEle(eles) {
// 转为数组过滤出包含 active 类的元素出队
return [...eles].filter(ele => ele.classList.contains('active')).shift();
}
// 设置激活的元素
function setActiveEle(index) {
//第 index 图片和按钮激活时
[imgs, btns].forEach(eles => eles.forEach(ele => {
// 取消当前元素激活
if (ele.classList.contains('active')) ele.classList.remove('active');
// 激活第 index 的图片和按钮
if (index === ele.dataset.index) ele.classList.add('active');
}
));
}
// 为每个小按钮添加点击事件
btns.forEach(btn => {
btn.addEventListener('click', ev => setActiveEle(ev.target.dataset.index));
});
// 为prev前翻页元素添加事件监听器
skip.firstElementChild.addEventListener('click', skipImg);
// 为next后翻页元素添加事件监听器
skip.lastElementChild.addEventListener('click', skipImg);
// 前后prev|next翻页点击事件的回调函数
function skipImg(ev) {
// 计算前后翻页点击时,图片组的图片或按钮组的按钮,处以激活状态的位置索引
let posIndex = parseInt(getActiveEle(imgs).dataset.index);
//console.log(posIndex);
// 向前翻页时(包含一个css类prev)
if (ev.target.classList.contains('prev')) {
if (0 === posIndex) {
// 原激活索引是 0,表示前面没有图片,则赋值最后一个图片的位置索引
posIndex = imgs.length - 1;
} else {
// 否则,表示前面还有图片,赋值前一个图片的位置索引,供前翻页激活
posIndex -= 1;
}
}
// 向后翻页时(包含一个css类next)
if (ev.target.classList.contains('next')) {
if (posIndex === imgs.length - 1) {
// 原激活索引是最后一个图片,表示后面没有没有图片了,赋值第一个图片的索引
posIndex = 0;
} else {
// 否则,表示后面还有图片,赋值后一个图片的位置索引,供后翻页激活
posIndex += 1;
}
}
// 激活第 posIndex 元素(图片|按钮)
//console.log(posIndex);
setActiveEle(posIndex.toString());
}
// 定义一个点击事件
let clickEvent = new Event('click');
// 页面载入时,为next后翻页元素,定时器间隔派发点击事件
let timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), 2000);
// 事件代理,鼠标移入/出轮播区时,事件派发执行
const slider = document.querySelector('.container');
// 鼠标移出轮播区域自动轮播
slider.addEventListener('mouseout', () => {
// 为next后翻页元素,定时器间隔派发点击事件
timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), 2000);
});
// 鼠标移入轮播区域停止轮播
slider.addEventListener('mouseover', () => {
// 清除定时器
clearInterval(timer);
});
</script>
简单封装
- 新建 html 文档,简单封装
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>轮播图</title>
<link rel="stylesheet" href="banner/style.css" />
</head>
<body>
<div class="container">
<!-- 1. 图片组,使用封装,去除自定义属性索引 -->
<nav class="imgs">
<a href="#"><img src="banner/banner1.jpg" alt="" /></a>
<a href="#"><img src="banner/banner2.jpg" alt="" /></a>
<a href="#"><img src="banner/banner3.jpg" alt="" /></a>
<a href="#"><img src="banner/banner4.jpg" alt="" /></a>
</nav>
<!-- 2. 图片小按钮 -->
<nav class="btns"></nav>
<!-- 3. 翻页 -->
<nav class="skip">
<a href="#"><</a>
<a href="#">></a>
</nav>
</div>
<script>
class Slider {
// 构造方法
constructor(slider = { container: '.container', slide: '.slide' }) {
this.slider = slider;
// 外层容器
this.container = this.slider['container'];
// 轮播的项目
this.slide = this.slider['slide'];
// 按钮组
this.btns = 'undefined' !== typeof this.slider['btns'] ? this.slider['btns'] : '.btns';
// 前后翻页
this.skip = 'undefined' !== typeof this.slider['skip'] ? this.slider['skip'] : '.skip';
// 事件类型
this.event = 'undefined' !== typeof this.slider['event'] ? this.slider['event'] : 'click';
// 载入时自动播放
this.autoplay = 'undefined' !== typeof this.slider['autoplay'] ? this.slider['autoplay'] : true;
// 播放延时
this.time = 'undefined' !== typeof this.slider['time'] ? this.slider['time'] : 2000;
// 初始化并执行
this.init();
}
// 执行函数
init() {
// 项目组
const imgs = document.querySelectorAll(this.slide);
// 按钮组
const btnGroup = document.querySelector(this.btns);
// 翻页按钮
const skip = document.querySelector(this.skip);
// 为项目组每个项目添加自定义属性索引
imgs.forEach((img, i) => {
img.dataset.index = i;
if (i === 0) img.classList.add('active');
});
// 根据项目数量向按钮组btnGroup添加项目数量个按钮
autoCreateBtns(btnGroup, imgs);
function autoCreateBtns(btnGroup, imgs) {
imgs.forEach((img, i) => {
// 创建并设置 a 标签属性
let a = document.createElement('a');
a.href = "#";
a.dataset.index = i;
// 图片处以激活时,对应的按钮也处于激活状态
if (img.classList.contains('active')) {
a.classList.add('active');
}
// 追加到父级元素
btnGroup.appendChild(a);
});
}
// 获取按钮组
const btns = Array.from(document.querySelector(this.btns).children);
// 获取激活的项目
function getActiveEle(eles) {
// 转为数组过滤出包含 active 类的元素出队
return [...eles].filter(ele => ele.classList.contains('active')).shift();
}
// 设置激活的元素
function setActiveEle(index) {
//第 index 图片和按钮激活时
[imgs, btns].forEach(eles => eles.forEach(ele => {
// 取消当前元素激活
if (ele.classList.contains('active')) ele.classList.remove('active');
// 激活第 index 的图片和按钮
if (index === ele.dataset.index) ele.classList.add('active');
}
));
}
// 为每个小按钮添加点击事件
btns.forEach(btn => {
btn.addEventListener(this.event, ev => setActiveEle(ev.target.dataset.index));
});
// 为prev前翻页元素添加事件监听器
skip.firstElementChild.classList.add('prev');
skip.firstElementChild.addEventListener(this.event, skipImg);
// 为next后翻页元素添加事件监听器
skip.lastElementChild.classList.add('next');
skip.lastElementChild.addEventListener(this.event, skipImg);
// 前后prev|next翻页点击事件的回调函数
function skipImg(ev) {
// 计算前后翻页点击时,图片组的图片或按钮组的按钮,处以激活状态的位置索引
let posIndex = parseInt(getActiveEle(imgs).dataset.index);
//console.log(posIndex);
// 向前翻页时(包含一个css类prev)
if (ev.target.classList.contains('prev')) {
if (0 === posIndex) {
// 原激活索引是 0,表示前面没有图片,则赋值最后一个图片的位置索引
posIndex = imgs.length - 1;
} else {
// 否则,表示前面还有图片,赋值前一个图片的位置索引,供前翻页激活
posIndex = posIndex - 1;
}
}
// 向后翻页时(包含一个css类next)
if (ev.target.classList.contains('next')) {
if (posIndex === imgs.length - 1) {
// 原激活索引是最后一个图片,表示后面没有没有图片了,赋值第一个图片的索引
posIndex = 0;
} else {
// 否则,表示后面还有图片,赋值后一个图片的位置索引,供后翻页激活
posIndex = posIndex + 1;
}
}
// 激活第 posIndex 元素(图片|按钮)
//console.log(posIndex);
setActiveEle(posIndex.toString());
}
// 定义一个点击事件
let clickEvent = new Event(this.event);
// 页面载入时,为next后翻页元素,定时器间隔派发点击事件
let timer = null;
// 如果载入时,允许进入自动播放
if (this.autoplay) {
timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), this.time);
}
// 事件代理,鼠标移入/出轮播区时,事件派发执行
const slider = document.querySelector('.container');
// 鼠标移出轮播区域自动轮播
slider.addEventListener('mouseout', () => {
// 为next后翻页元素,定时器间隔派发点击事件
timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), this.time);
});
// 鼠标移入轮播区域停止轮播
slider.addEventListener('mouseover', () => {
// 清除定时器
clearInterval(timer);
});
}
}
// 调用
let slider = new Slider({
container: '.container', // 外层容器
slide: '.container > .imgs img', // 轮播的项目
btns: '.container > .btns', // 生成按钮组的容器css
skip: '.container > .skip', // 前后翻页的css
event: 'click', // 事件类型
autoplay: true, // 载入时是否允许自动播放
time: 2000 // 延时间隔时间
});
</script>
</body>
</html>
- 页面载入播放图
图片懒加载
-
body
中国添加 html 和 js
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/190824/212516-1566653116f355.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/201228/214304-16091629844780.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/200618/005100-1592412660f973.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/180826/113958-1535254798fc1c.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/180315/110404-152108304476cb.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/170609/123945-14969831856c4d.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/200410/213246-1586525566e909.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/190917/183634-15687165942ef2.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/180803/084010-15332568109b5b.jpg" alt=""></p>
<p><img src="http://pic.netbian.com/static/img/logo.jpg"
data-src="http://pic.netbian.com/uploads/allimg/190518/174718-15581728388724.jpg" alt=""></p>
<script>
const imgs = document.querySelectorAll('p > img');
// 视口高度
let clientHeight = document.documentElement.clientHeight;
// 窗口滚动监听
window.addEventListener('scroll', lazyload);
// 页面加载完成执行
window.addEventListener('load', lazyload);
// 回调函数
function lazyload() {
// 滚动高度
let scrollTop = document.documentElement.scrollTop;
// 图片遍历
imgs.forEach(img => {
// 图片高度 < 视口高度 + 滚动高度,图片进入视口
if (img.offsetTop < clientHeight + scrollTop) {
img.src = img.dataset.src;
}
});
}
</script>
- 页面从第3个图片起,未进入视口范围,显示默认替代 logo 图片