一、图片懒加载
1.图片懒加载原理
将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名,我才用data-src)属性指向真实的图片。src指向一张默认的图片,否则当src为空时也会向服务器发送一次请求。可以指向loading的地址。
<!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>
</head>
<body>
<img src="images1/default.png" data-src="./images1/5.jpg" alt="" width="660" />
<script>
// 1.文档坐标: html文档,一旦渲染完成,它的大小是固定的
// 2.视口坐标: 用户看到的文档部分,窗口显示的文档部分
// 文档与视口之间的关系:
// 1. 文档 小于或等于 视口
// 一屏就可以将整个文档显示完成,没有滚动条,例如 baidu
// 2. 文档 大于 视口
// 这是常态, 一屏就显示不完,会出现滚动条,通过拖动滚动条查看更多内容
// 例如 php.cn
// 视口高度
let viewHeight = document.documentElement.clientHeight;
console.log(viewHeight);
document.documentElement.style.height = "1000px";
// 滚动高度
// 通常只需要关注高度即可,因为宽度是受限的,高度是随内容扩展的
console.log(document.documentElement.scrollTop);
// 滚动事件
window.onscroll = function () {
const img = document.querySelector("img");
// img.src = img.dataset.src;
setTimeout(function () {
img.src = img.dataset.src;
}, 2000);
};
</script>
</body>
</html>
2.图片懒加载实现
<!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>
<style>
.container {
width: 500px;
display: grid;
gap: 10px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.container img {
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<img src="images2/temp.jpg" alt="" data-src="images2/img-1.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-2.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-3.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-4.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-5.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-6.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-7.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-8.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-9.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-10.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-11.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-12.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-13.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-14.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-15.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-16.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-17.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-18.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-19.jpg" />
<img src="images2/temp.jpg" alt="" data-src="images2/img-20.jpg" />
</div>
<script>
// 所有图片
const imgs = document.querySelectorAll(".container img");
// const imgs = document.images;
// 视口高度
const clientHeight = document.documentElement.clientHeight;
// 监听滚动事件
// "scroll": 滚动事件, onscroll: 事件属性,不是事件名称
window.addEventListener("scroll", layzyload);
// 当页面加载完成后立即显示第一屏
window.addEventListener("load", layzyload);
// 懒加载的回调
function layzyload() {
// 滚动距离
let scrollTop = document.documentElement.scrollTop;
imgs.forEach(img => {
// 这张图片的顶部距离它的父级的高度,是否小于视口高度与滚动距离之和
if (img.offsetTop < clientHeight + scrollTop) {
setTimeout(function () {
img.src = img.dataset.src;
}, 500);
}
});
}
</script>
</body>
</html>
二、轮播图
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="banner/banner.css" />
</head>
<body>
<div class="container">
<!-- 1. 图片组 -->
<nav class="imgs">
<a href=""><img src="banner/banner1.jpg" alt="" data-index="1" class="active" /></a>
<a href=""><img src="banner/banner2.jpg" alt="" data-index="2" /></a>
<a href=""><img src="banner/banner3.jpg" alt="" data-index="3" /></a>
<a href=""><img src="banner/banner4.jpg" alt="" data-index="4" /></a>
</nav>
<!-- 2. 图片中下部的小按钮 -->
<nav class="btns">
<!-- 小按钮数量必须与图片数量一致所以应该动态创建 -->
<!-- <a href="" data-index="1" class="active"></a>
<a href="" data-index="2"></a>
<a href="" data-index="3"></a>
<a href="" data-index="4"></a> -->
</nav>
<!-- 3. 翻页 -->
<nav class="skip">
<a href="" class="prev"><</a>
<a href="" class="next">></a>
</nav>
</div>
<script>
//所有图片
const imgs = document.querySelectorAll(".container >.imgs img");
//按钮组
const btnGroup = document.querySelector(".container > .btns");
//翻页按钮
const skip = document.querySelector(".container > .skip");
//创建出一组与图片数量对应的小按钮
function autoCrateBtns(ele, imgLength) {
//复用文档片断来简化/优化编程
const frag = document.createDocumentFragment();
for (let i = 0; i < imgLength; i++) {
const a = document.createElement("a");
a.href = "#";
a.dataset.index = i + 1;
if (i === 0) a.classList.add("active");
frag.append(a);
}
ele.append(frag);
}
autoCrateBtns(btnGroup, imgs.length);
// 为刚刚生成的小按钮添加点击事件
const btns = document.querySelectorAll(".container > .btns > *");
// 二个公共函数
// 1. 获取激活的元素
function getActiveEle(eles) {
// 将元素集合转为真正的数组
// console.log([...eles]);
let activeEles = [...eles].filter(ele => ele.classList.contains("active"));
// console.log(activeEles.shift());
return activeEles.shift();
}
// getActiveEle(btns);
// getActiveEle(imgs);
// 2. 设置激活的元素,根据按钮索引更新正在显示的图片
// 参数就是当前正在点击的按钮的索引
function setActiveEle(btnIndex) {
// console.log(btnIndex);
// console.log(imgs, btns);
// 1.先将之前的激活的样式去掉
[imgs, btns].forEach(arr => {
getActiveEle(arr).classList.remove("active");
// 2.再根据当前的的自定义索引来重新设置应该激活的按钮和图片
arr.forEach(item => {
if (item.dataset.index === btnIndex) {
item.classList.add("active");
}
});
});
}
// 为按钮添加事件
btns.forEach(btn => btn.addEventListener("click", ev => setActiveEle(ev.target.dataset.index)));
// 思考:
// 1. 为翻页按钮添加点击事件,注意最后一张和第一张图片的边界处理
// 2. 实现轮播图的定时播放
// 鼠标移入时关闭自动播放,移出时启动自动播放
// setInterval(),间歇式定时器(重复执行)
// dispathEvent(): 事件派发器
</script>
</body>
</html>
banner.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;
}