PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

博客列表 > 轮播图-添加翻页-自动播放-图片懒加载

轮播图-添加翻页-自动播放-图片懒加载

葡萄枝子
葡萄枝子 原创
2021年01月12日 18:16:16 1176浏览

轮播图-添加翻页-自动播放-图片懒加载

  1. 为翻页按钮添加功能
  2. 当鼠标移出时,图片的每隔2秒的自动播放,当鼠标移入时自动停止播放
  3. 上节课的选项卡, 懒加载二选一

1和2轮播图,添加翻页和隔两秒自动播放

  • head 标签添加
  1. <link rel="stylesheet" href="banner/style.css" />
  • 引入的banner/style.css是默认的
  1. /* 初始化 */
  2. * {
  3. margin: 0;
  4. padding: 0;
  5. box-sizing: border-box;
  6. }
  7. a {
  8. text-decoration: none;
  9. }
  10. /* 轮播图的容器 */
  11. .container {
  12. width: 62.5em;
  13. height: 22em;
  14. margin: 1em auto;
  15. /* 转为定位元素/定位父级 */
  16. position: relative;
  17. }
  18. /* 图片组 */
  19. .container > .imgs img {
  20. width: 100%;
  21. height: 100%;
  22. /* 默认全部隐藏 */
  23. display: none;
  24. /* 将所有的图片进行绝对定位,确保每一次只看到一张,所有图片共享这个容器 */
  25. position: absolute;
  26. left: 0;
  27. top: 0;
  28. }
  29. /* 设置默认显示的图片(第一张) */
  30. .container > .imgs img.active {
  31. display: block;
  32. }
  33. /* 按钮组(独立按钮) */
  34. .container > .btns {
  35. position: absolute;
  36. left: 0;
  37. right: 0;
  38. bottom: 0;
  39. /* 水平居中 */
  40. text-align: center;
  41. }
  42. .container > .btns a {
  43. /* 转成行内块元素: 即能水平排列,双支持宽度设置 */
  44. display: inline-block;
  45. padding: 0.5em;
  46. margin: 0 0.2em;
  47. background-color: #fff;
  48. border-radius: 50%;
  49. }
  50. .container > .btns a.active {
  51. background-color: #000;
  52. }
  53. /* 翻页按钮 */
  54. .container .skip a {
  55. position: absolute;
  56. width: 2.5rem;
  57. height: 5rem;
  58. line-height: 5rem;
  59. text-align: center;
  60. opacity: 0.3;
  61. top: 9rem;
  62. font-weight: lighter;
  63. font-size: 2rem;
  64. background-color: #ccc;
  65. }
  66. .container .skip .prev {
  67. left: 0;
  68. }
  69. .container .skip .next {
  70. right: 0;
  71. }
  72. .container .skip *:hover {
  73. opacity: 0.6;
  74. color: #666;
  75. }
  • body 中添加html是默认的
  1. <div class="container">
  2. <!-- 1. 图片组 -->
  3. <nav class="imgs">
  4. <a href="#"><img src="banner/banner1.jpg" alt="" data-index="0" class="active" /></a>
  5. <a href="#"><img src="banner/banner2.jpg" alt="" data-index="1" /></a>
  6. <a href="#"><img src="banner/banner3.jpg" alt="" data-index="2" /></a>
  7. <a href="#"><img src="banner/banner4.jpg" alt="" data-index="3" /></a>
  8. </nav>
  9. <!-- 2. 图片小按钮 -->
  10. <nav class="btns">
  11. <!-- 这些小按钮应该根据图片数量自动生成 -->
  12. <!-- <a href="" data-index="0" class="active"></a>
  13. <a href="" data-index="1"></a>
  14. <a href="" data-index="2"></a>
  15. <a href="" data-index="3"></a> -->
  16. </nav>
  17. <!-- 3. 翻页 -->
  18. <nav class="skip">
  19. <a href="#" class="prev">&lt;</a>
  20. <a href="#" class="next">&gt;</a>
  21. </nav>
  22. </div>
  • 续写 js 图片轮播
  1. <script>
  2. // 图片组
  3. const imgs = document.querySelectorAll(".container > .imgs img");
  4. // 按钮组
  5. const btnGroup = document.querySelector(".container > .btns");
  6. // 翻页按钮
  7. const skip = document.querySelector(".container > .skip");
  8. // 根据图片组imgs的图片数量向按钮组btnGroup添加图片数量个按钮
  9. function autoCreateBtns(btnGroup, imgs) {
  10. imgs.forEach((img, i) => {
  11. // 创建并设置 a 标签属性
  12. let a = document.createElement('a');
  13. a.href = "#";
  14. a.dataset.index = i;
  15. // 图片处以激活时,对应的按钮也处于激活状态
  16. if (img.classList.contains('active')) {
  17. a.classList.add('active');
  18. }
  19. // 追加到父级元素
  20. btnGroup.appendChild(a);
  21. });
  22. }
  23. autoCreateBtns(btnGroup, imgs)
  24. // 获取按钮组
  25. const btns = document.querySelectorAll(".container > .btns > *");
  26. // 获取激活的元素(图片|按钮)
  27. function getActiveEle(eles) {
  28. // 转为数组过滤出包含 active 类的元素出队
  29. return [...eles].filter(ele => ele.classList.contains('active')).shift();
  30. }
  31. // 设置激活的元素
  32. function setActiveEle(index) {
  33. //第 index 图片和按钮激活时
  34. [imgs, btns].forEach(eles => eles.forEach(ele => {
  35. // 取消当前元素激活
  36. if (ele.classList.contains('active')) ele.classList.remove('active');
  37. // 激活第 index 的图片和按钮
  38. if (index === ele.dataset.index) ele.classList.add('active');
  39. }
  40. ));
  41. }
  42. // 为每个小按钮添加点击事件
  43. btns.forEach(btn => {
  44. btn.addEventListener('click', ev => setActiveEle(ev.target.dataset.index));
  45. });
  46. // 为prev前翻页元素添加事件监听器
  47. skip.firstElementChild.addEventListener('click', skipImg);
  48. // 为next后翻页元素添加事件监听器
  49. skip.lastElementChild.addEventListener('click', skipImg);
  50. // 前后prev|next翻页点击事件的回调函数
  51. function skipImg(ev) {
  52. // 计算前后翻页点击时,图片组的图片或按钮组的按钮,处以激活状态的位置索引
  53. let posIndex = parseInt(getActiveEle(imgs).dataset.index);
  54. //console.log(posIndex);
  55. // 向前翻页时(包含一个css类prev)
  56. if (ev.target.classList.contains('prev')) {
  57. if (0 === posIndex) {
  58. // 原激活索引是 0,表示前面没有图片,则赋值最后一个图片的位置索引
  59. posIndex = imgs.length - 1;
  60. } else {
  61. // 否则,表示前面还有图片,赋值前一个图片的位置索引,供前翻页激活
  62. posIndex -= 1;
  63. }
  64. }
  65. // 向后翻页时(包含一个css类next)
  66. if (ev.target.classList.contains('next')) {
  67. if (posIndex === imgs.length - 1) {
  68. // 原激活索引是最后一个图片,表示后面没有没有图片了,赋值第一个图片的索引
  69. posIndex = 0;
  70. } else {
  71. // 否则,表示后面还有图片,赋值后一个图片的位置索引,供后翻页激活
  72. posIndex += 1;
  73. }
  74. }
  75. // 激活第 posIndex 元素(图片|按钮)
  76. //console.log(posIndex);
  77. setActiveEle(posIndex.toString());
  78. }
  79. // 定义一个点击事件
  80. let clickEvent = new Event('click');
  81. // 页面载入时,为next后翻页元素,定时器间隔派发点击事件
  82. let timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), 2000);
  83. // 事件代理,鼠标移入/出轮播区时,事件派发执行
  84. const slider = document.querySelector('.container');
  85. // 鼠标移出轮播区域自动轮播
  86. slider.addEventListener('mouseout', () => {
  87. // 为next后翻页元素,定时器间隔派发点击事件
  88. timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), 2000);
  89. });
  90. // 鼠标移入轮播区域停止轮播
  91. slider.addEventListener('mouseover', () => {
  92. // 清除定时器
  93. clearInterval(timer);
  94. });
  95. </script>

简单封装

  • 新建 html 文档,简单封装
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>轮播图</title>
  7. <link rel="stylesheet" href="banner/style.css" />
  8. </head>
  9. <body>
  10. <div class="container">
  11. <!-- 1. 图片组,使用封装,去除自定义属性索引 -->
  12. <nav class="imgs">
  13. <a href="#"><img src="banner/banner1.jpg" alt="" /></a>
  14. <a href="#"><img src="banner/banner2.jpg" alt="" /></a>
  15. <a href="#"><img src="banner/banner3.jpg" alt="" /></a>
  16. <a href="#"><img src="banner/banner4.jpg" alt="" /></a>
  17. </nav>
  18. <!-- 2. 图片小按钮 -->
  19. <nav class="btns"></nav>
  20. <!-- 3. 翻页 -->
  21. <nav class="skip">
  22. <a href="#">&lt;</a>
  23. <a href="#">&gt;</a>
  24. </nav>
  25. </div>
  26. <script>
  27. class Slider {
  28. // 构造方法
  29. constructor(slider = { container: '.container', slide: '.slide' }) {
  30. this.slider = slider;
  31. // 外层容器
  32. this.container = this.slider['container'];
  33. // 轮播的项目
  34. this.slide = this.slider['slide'];
  35. // 按钮组
  36. this.btns = 'undefined' !== typeof this.slider['btns'] ? this.slider['btns'] : '.btns';
  37. // 前后翻页
  38. this.skip = 'undefined' !== typeof this.slider['skip'] ? this.slider['skip'] : '.skip';
  39. // 事件类型
  40. this.event = 'undefined' !== typeof this.slider['event'] ? this.slider['event'] : 'click';
  41. // 载入时自动播放
  42. this.autoplay = 'undefined' !== typeof this.slider['autoplay'] ? this.slider['autoplay'] : true;
  43. // 播放延时
  44. this.time = 'undefined' !== typeof this.slider['time'] ? this.slider['time'] : 2000;
  45. // 初始化并执行
  46. this.init();
  47. }
  48. // 执行函数
  49. init() {
  50. // 项目组
  51. const imgs = document.querySelectorAll(this.slide);
  52. // 按钮组
  53. const btnGroup = document.querySelector(this.btns);
  54. // 翻页按钮
  55. const skip = document.querySelector(this.skip);
  56. // 为项目组每个项目添加自定义属性索引
  57. imgs.forEach((img, i) => {
  58. img.dataset.index = i;
  59. if (i === 0) img.classList.add('active');
  60. });
  61. // 根据项目数量向按钮组btnGroup添加项目数量个按钮
  62. autoCreateBtns(btnGroup, imgs);
  63. function autoCreateBtns(btnGroup, imgs) {
  64. imgs.forEach((img, i) => {
  65. // 创建并设置 a 标签属性
  66. let a = document.createElement('a');
  67. a.href = "#";
  68. a.dataset.index = i;
  69. // 图片处以激活时,对应的按钮也处于激活状态
  70. if (img.classList.contains('active')) {
  71. a.classList.add('active');
  72. }
  73. // 追加到父级元素
  74. btnGroup.appendChild(a);
  75. });
  76. }
  77. // 获取按钮组
  78. const btns = Array.from(document.querySelector(this.btns).children);
  79. // 获取激活的项目
  80. function getActiveEle(eles) {
  81. // 转为数组过滤出包含 active 类的元素出队
  82. return [...eles].filter(ele => ele.classList.contains('active')).shift();
  83. }
  84. // 设置激活的元素
  85. function setActiveEle(index) {
  86. //第 index 图片和按钮激活时
  87. [imgs, btns].forEach(eles => eles.forEach(ele => {
  88. // 取消当前元素激活
  89. if (ele.classList.contains('active')) ele.classList.remove('active');
  90. // 激活第 index 的图片和按钮
  91. if (index === ele.dataset.index) ele.classList.add('active');
  92. }
  93. ));
  94. }
  95. // 为每个小按钮添加点击事件
  96. btns.forEach(btn => {
  97. btn.addEventListener(this.event, ev => setActiveEle(ev.target.dataset.index));
  98. });
  99. // 为prev前翻页元素添加事件监听器
  100. skip.firstElementChild.classList.add('prev');
  101. skip.firstElementChild.addEventListener(this.event, skipImg);
  102. // 为next后翻页元素添加事件监听器
  103. skip.lastElementChild.classList.add('next');
  104. skip.lastElementChild.addEventListener(this.event, skipImg);
  105. // 前后prev|next翻页点击事件的回调函数
  106. function skipImg(ev) {
  107. // 计算前后翻页点击时,图片组的图片或按钮组的按钮,处以激活状态的位置索引
  108. let posIndex = parseInt(getActiveEle(imgs).dataset.index);
  109. //console.log(posIndex);
  110. // 向前翻页时(包含一个css类prev)
  111. if (ev.target.classList.contains('prev')) {
  112. if (0 === posIndex) {
  113. // 原激活索引是 0,表示前面没有图片,则赋值最后一个图片的位置索引
  114. posIndex = imgs.length - 1;
  115. } else {
  116. // 否则,表示前面还有图片,赋值前一个图片的位置索引,供前翻页激活
  117. posIndex = posIndex - 1;
  118. }
  119. }
  120. // 向后翻页时(包含一个css类next)
  121. if (ev.target.classList.contains('next')) {
  122. if (posIndex === imgs.length - 1) {
  123. // 原激活索引是最后一个图片,表示后面没有没有图片了,赋值第一个图片的索引
  124. posIndex = 0;
  125. } else {
  126. // 否则,表示后面还有图片,赋值后一个图片的位置索引,供后翻页激活
  127. posIndex = posIndex + 1;
  128. }
  129. }
  130. // 激活第 posIndex 元素(图片|按钮)
  131. //console.log(posIndex);
  132. setActiveEle(posIndex.toString());
  133. }
  134. // 定义一个点击事件
  135. let clickEvent = new Event(this.event);
  136. // 页面载入时,为next后翻页元素,定时器间隔派发点击事件
  137. let timer = null;
  138. // 如果载入时,允许进入自动播放
  139. if (this.autoplay) {
  140. timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), this.time);
  141. }
  142. // 事件代理,鼠标移入/出轮播区时,事件派发执行
  143. const slider = document.querySelector('.container');
  144. // 鼠标移出轮播区域自动轮播
  145. slider.addEventListener('mouseout', () => {
  146. // 为next后翻页元素,定时器间隔派发点击事件
  147. timer = setInterval(() => skip.lastElementChild.dispatchEvent(clickEvent), this.time);
  148. });
  149. // 鼠标移入轮播区域停止轮播
  150. slider.addEventListener('mouseover', () => {
  151. // 清除定时器
  152. clearInterval(timer);
  153. });
  154. }
  155. }
  156. // 调用
  157. let slider = new Slider({
  158. container: '.container', // 外层容器
  159. slide: '.container > .imgs img', // 轮播的项目
  160. btns: '.container > .btns', // 生成按钮组的容器css
  161. skip: '.container > .skip', // 前后翻页的css
  162. event: 'click', // 事件类型
  163. autoplay: true, // 载入时是否允许自动播放
  164. time: 2000 // 延时间隔时间
  165. });
  166. </script>
  167. </body>
  168. </html>
  • 页面载入播放图

轮播图

图片懒加载

  • body 中国添加 html 和 js
  1. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  2. data-src="http://pic.netbian.com/uploads/allimg/190824/212516-1566653116f355.jpg" alt=""></p>
  3. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  4. data-src="http://pic.netbian.com/uploads/allimg/201228/214304-16091629844780.jpg" alt=""></p>
  5. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  6. data-src="http://pic.netbian.com/uploads/allimg/200618/005100-1592412660f973.jpg" alt=""></p>
  7. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  8. data-src="http://pic.netbian.com/uploads/allimg/180826/113958-1535254798fc1c.jpg" alt=""></p>
  9. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  10. data-src="http://pic.netbian.com/uploads/allimg/180315/110404-152108304476cb.jpg" alt=""></p>
  11. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  12. data-src="http://pic.netbian.com/uploads/allimg/170609/123945-14969831856c4d.jpg" alt=""></p>
  13. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  14. data-src="http://pic.netbian.com/uploads/allimg/200410/213246-1586525566e909.jpg" alt=""></p>
  15. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  16. data-src="http://pic.netbian.com/uploads/allimg/190917/183634-15687165942ef2.jpg" alt=""></p>
  17. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  18. data-src="http://pic.netbian.com/uploads/allimg/180803/084010-15332568109b5b.jpg" alt=""></p>
  19. <p><img src="http://pic.netbian.com/static/img/logo.jpg"
  20. data-src="http://pic.netbian.com/uploads/allimg/190518/174718-15581728388724.jpg" alt=""></p>
  21. <script>
  22. const imgs = document.querySelectorAll('p > img');
  23. // 视口高度
  24. let clientHeight = document.documentElement.clientHeight;
  25. // 窗口滚动监听
  26. window.addEventListener('scroll', lazyload);
  27. // 页面加载完成执行
  28. window.addEventListener('load', lazyload);
  29. // 回调函数
  30. function lazyload() {
  31. // 滚动高度
  32. let scrollTop = document.documentElement.scrollTop;
  33. // 图片遍历
  34. imgs.forEach(img => {
  35. // 图片高度 < 视口高度 + 滚动高度,图片进入视口
  36. if (img.offsetTop < clientHeight + scrollTop) {
  37. img.src = img.dataset.src;
  38. }
  39. });
  40. }
  41. </script>
  • 页面从第3个图片起,未进入视口范围,显示默认替代 logo 图片

懒加载

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议