Blogger Information
Blog 13
fans 0
comment 0
visits 9218
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
简单设计案例:选项卡、图片懒加载、轮播图
我是贝壳
Original
685 people have browsed it

简单设计案例:选项卡、图片懒加载、轮播图

1、选项卡

本次简单选项卡主要是一个三选容器,当点击其中某个选项时,其他的选项会被覆盖。

html代如下:

  1. <div class="tabs">
  2. <!-- 导航 -->
  3. <ul class="tab">
  4. <li class="active" data-index="1">家事</li>
  5. <li data-index="2">国事</li>
  6. <li data-index="3">世事</li>
  7. </ul>
  8. <!-- details -->
  9. <ul data-index="1" class="item active">
  10. <li><a href="">腊月完婚好开心</a></li>
  11. <li><a href="">开始小新婚生活</a></li>
  12. <li><a href="">开始造人小计划</a></li>
  13. </ul>
  14. <ul data-index="2" class="item">
  15. <li><a href="">疫情开始有转机</a></li>
  16. <li><a href="">新年春运不停站</a></li>
  17. <li><a href="">勤洗手讲究卫生</a></li>
  18. </ul>
  19. <ul data-index="3" class="item">
  20. <li><a href="">特朗普离职演讲</a></li>
  21. <li><a href="">多国疫情再变异</a></li>
  22. <li><a href="">丰田扩中国市场</a></li>
  23. </ul>
  24. </div>

对应css代码如下:

  1. <style>
  2. * {
  3. margin: 0;
  4. padding: 0;
  5. box-sizing: border-box;
  6. }
  7. a {
  8. color: #555;
  9. text-decoration: none;
  10. }
  11. a:hover {
  12. color: red;
  13. text-decoration: underline;
  14. }
  15. li {
  16. list-style: none;
  17. line-height: 1.6rem;
  18. }
  19. li:hover {
  20. cursor: default;
  21. }
  22. .tabs {
  23. width: 300px;
  24. height: 300px;
  25. margin: 30px;
  26. background-color: #e6e6e6;
  27. display: flex;
  28. flex-direction: column;
  29. }
  30. .tab {
  31. display: flex;
  32. height: 36px;
  33. }
  34. .tab li {
  35. flex: auto;
  36. text-align: center;
  37. height: 36px;
  38. background-color: #fff;
  39. }
  40. .tab li.active {
  41. background-color: #e6e6e6;
  42. }
  43. .tab li:hover {
  44. cursor: pointer;
  45. }
  46. /* 默认所有选项卡只有一个显示,其它隐藏 */
  47. .item {
  48. padding: 20px;
  49. display: none;
  50. }
  51. /* .item和.active之间不能有空格 */
  52. .item.active {
  53. display: block;
  54. }
  55. </style>

js代码如下:

  1. <script>
  2. const tab = document.querySelector(".tab");
  3. const items = document.querySelectorAll(".item");
  4. tab.onclick = (ev) => {
  5. // console.log(ev.target);
  6. // console.log(ev.currentTarget);
  7. //点中选项卡中任一个,先将所有选项卡active清空,然后再将找到触发对象设置active
  8. [...tab.children].forEach((item) => item.classList.remove("active"));
  9. ev.target.classList.add("active");
  10. //联动操作选项卡对应的新闻列表
  11. //同样要先清空所有item的active,通过ev触发对象data-index属性来找到对应item,然后添加active
  12. items.forEach((item) => {
  13. item.classList.remove("active");
  14. });
  15. //通过filter来找对应的新闻内容列表,添加active类属性
  16. [...items]
  17. .filter((item) => item.dataset.index === ev.target.dataset.index)[0]
  18. .classList.add("active");
  19. };
  20. </script>

总体上的思路:设置选项卡与对应的新闻列表的某个属性一致,如代码中的 ul.tab.li 和 下面的ul.item都会有一个相同自定义属性data-index,选中ul.tab.li时,通过其data-index属性找到其他的ul并设置为不显示(display:none) ,剩下ul设置为display:block;

2、图片懒加载

解析:
当遇到页面上需要加载特别多的图片或者视频文件时,我们希望加载页面时,不要一次性将所有文件渲染到页面中,这样会浪费较多计算机的资源,我们希望当文件进入到用户视野时,再渲染文件,这样不仅灵活,也能节省计算机资源。

两个概念:

可视区高度:打开浏览器,在没有滚动条时,能加载内容的最大高度。
滚动高度:下拉进度条离可视区顶部的距离

所以什么情况下,文件算是进入到用户的视野

文件的顶部距离 < 可视区刻度+滚动高度

示范代码:

  1. //假设html代码中添加了80张图片,
  2. <img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />
  3. 。。。
  4. <img src="images/temp.jpg" alt="" data-src="images/img-80.jpg" />

js代码:

控制当文件的顶部距离<可视区高度+滚动高度时,用自定义属性data-src的属性值替代原有src属性值,同时为了不让图片显示比较突兀,还通过setTimeout来让图片在0.5秒后开始加载。由于高度数据在不断变化,所以需要给window添加监听器。

  1. <script>
  2. const imgs = document.querySelectorAll(".container img");
  3. const clientHeight = document.documentElement.clientHeight;
  4. window.addEventListener("scroll", layzyload);
  5. // load:页面加载完成自动执行
  6. window.addEventListener("load", layzyload);
  7. function layzyload() {
  8. // 滚动高度
  9. let scrollTop = document.documentElement.scrollTop;
  10. // 遍历图片并判断是否进入到了可视区
  11. imgs.forEach((img) => {
  12. // 只要当前图片距离文档顶部的偏移量,小于可视区高度与滚动高度之间则表示进入到可视区,应该显示出来
  13. // clientHeight是可视区高度,这是一个固定的值,滚动高度是动态的
  14. if (img.offsetTop < clientHeight + scrollTop) {
  15. setTimeout(() => (img.src = img.dataset.src), 500);
  16. }
  17. });
  18. }
  19. </script>

3、轮播图

我们希望实现的轮播图,如京东等购物网站首页

  1. 图片下方有一组小按钮,能够指定显示图上;
  2. 在图片的两侧分别有一个箭头,可以实现上一张和下一张浏览
  3. 鼠标事件,当鼠标移出轮播图区域时,图片以两秒的间隔进行轮播

html代码:

  1. <div class="container" >
  2. <!-- 1 图片组 -->
  3. <nav class="imgs">
  4. <img src="../../21/0111/banner/banner1.jpg" alt="" class="active" data-index="1" />
  5. <img src="../../21/0111/banner/banner2.jpg" data-index="2" alt="" />
  6. <img src="../../21/0111/banner/banner3.jpg" data-index="3" alt="" />
  7. <img src="../../21/0111/banner/banner4.jpg" data-index="4" alt="" />
  8. </nav>
  9. <!-- 2 按钮组 -->
  10. <nav class="btns">
  11. <!-- 不直接定义按钮数量,根据图片数据生成 -->
  12. </nav>
  13. <!-- 3. 翻页 -->
  14. <nav class="skip">
  15. <a href="#" class="prev">&lt;</a>
  16. <a href="#" class="next">&gt;</a>
  17. </nav>
  18. </div>

css代码:

  1. * {
  2. margin: 0px;
  3. padding: 0px;
  4. box-sizing: border-box;
  5. }
  6. a {
  7. text-decoration: none;
  8. }
  9. .container {
  10. width: 62.5em;
  11. height: 22em;
  12. margin: 1em auto;
  13. /* 转为定位元素/定位父级 */
  14. position: relative;
  15. }
  16. /* 图片组样式 */
  17. .container > .imgs img {
  18. width: 100%;
  19. height: 100%;
  20. display: none;
  21. /* 将所有的图片进行绝对定位,确保每一次只看到一张,所有图片共享这个容器 */
  22. position: absolute;
  23. left: 0;
  24. top: 0;
  25. }
  26. .container > .imgs img.active {
  27. display: block;
  28. }
  29. /* 设置按钮组样式 */
  30. .container > .btns {
  31. position: absolute;
  32. left: 0;
  33. right: 0;
  34. bottom: 0;
  35. /* 水平居中 */
  36. text-align: center;
  37. }
  38. .container > .btns a.active {
  39. background-color: #000;
  40. }
  41. .container > .btns > a {
  42. /* 转成行内块元素: 即能水平排列,双支持宽度设置 */
  43. display: inline-block;
  44. padding: 0.5em;
  45. margin: 0 0.2em;
  46. background-color: #fff;
  47. border-radius: 50%;
  48. }
  49. /* .container > .btns a.active {
  50. background-color: #000;
  51. } */
  52. /* 翻页按钮 */
  53. .container .skip a {
  54. position: absolute;
  55. width: 2.5rem;
  56. height: 5rem;
  57. line-height: 5rem;
  58. text-align: center;
  59. opacity: 0.3;
  60. top: 9rem;
  61. font-weight: lighter;
  62. font-size: 2rem;
  63. background-color: #ccc;
  64. }
  65. .container .skip .prev {
  66. left: 0;
  67. }
  68. .container .skip .next {
  69. right: 0;
  70. }
  71. .container .skip *:hover {
  72. opacity: 0.6;
  73. color: #666;
  74. }

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.querySelectorAll(".container > .skip > a");
  8. // 方法1:获取图片数量生成对应的按钮组,遍历时每次插入一个a标签
  9. // imgs.forEach((img, i = 0) => {
  10. // let btnHtml = `<a href="#" data-index="${i + 1}"></a>`;
  11. // if (i === 0)
  12. // btnHtml = `<a href="#" class="active" data-index="${i + 1}"></a>`;
  13. // console.log(btnHtml);
  14. // btns.insertAdjacentHTML("beforeEnd", btnHtml);
  15. // i++;
  16. // });
  17. // 方法2:函数,创建一个文件片断,先创建对应数量的a标签,再统一将文件片断添加到对应的btnGroup里面
  18. function autoCreateBtns(ele, imgLength) {
  19. const frag = document.createDocumentFragment();
  20. for (let i = 0; i < imgLength; i++) {
  21. let a = document.createElement("a");
  22. a.href = "#";
  23. a.dataset.index = i + 1;
  24. if (i === 0) a.classList.add("active");
  25. frag.appendChild(a);
  26. }
  27. ele.appendChild(frag);
  28. }
  29. // 调用函数,传入按钮组和图片数量到btnGroup
  30. autoCreateBtns(btnGroup, imgs.length);
  31. //思考:要求1中按钮组事件与要求2翻页按钮具有共性,假设具有active类属性的对象为显示状态,不具有active类属性的对象显示隐藏,那么当我们触发一个事件时,都需要将某一个集合的对象全部移除active属性,同时将需要将某个集合中的指定元素添加acitve类属性,所以这里可以写三个公共函数:
  32. //全部移除active属性
  33. function removeActive(ele){
  34. [...ele].forEach((item) => item.classList.remove("active"));
  35. }
  36. //弹出集合中中具有active属性的对象
  37. function getActiveEle(ele) {
  38. let activities = [...ele].filter((item) =>
  39. item.classList.contains("active")
  40. );
  41. return activities.shift();
  42. }
  43. //将指定元素Index添加active属性,其余去掉active属性
  44. function setActiveEle2(ele, index) {
  45. [...ele].forEach((item) => {
  46. if (item.dataset.index == index) {
  47. item.classList.add("active");
  48. } else {
  49. item.classList.remove("active");
  50. }
  51. });
  52. //要求1:图片下方有一组小按钮,能够指定显示图上
  53. btns.forEach((btn) =>
  54. btn.addEventListener("click", (ev) => {
  55. removeActiveEle([...btns]);
  56. removeActiveEle([...imgs]);
  57. setActiveEle2([...btns], ev.target.dataset.index);
  58. setActiveEle2([...imgs], ev.target.dataset.index);
  59. })
  60. );
  61. //要求2. 在图片的两侧分别有一个箭头,可以实现上一张和下一张浏览
  62. //思路:当时没到尽头时,图片直接显示index-1就行,到尽头时,需要跳转到另一端的尽头
  63. //简化:这里面都是非黑即白的判断,前一张或者后一张,到尽头还是没到尽头,可以用三元运算符来简化代码
  64. skip.forEach((item) =>
  65. item.addEventListener("click", (ev) => {
  66. let previndex = getActiveEle(imgs).dataset.index - 1;
  67. let nextindex = parseInt(getActiveEle(imgs).dataset.index) + 1;
  68. if (ev.target.className == "prev") {
  69. if (previndex != 0) {
  70. //没到尽头,直接显示previndex
  71. removeActiveEle([...btns]);
  72. removeActiveEle([...imgs]);
  73. setActiveEle2([...imgs], previndex);
  74. setActiveEle2([...btns], previndex);
  75. } else {
  76. //到尽头,直接跳转另一端的尽头
  77. removeActiveEle([...btns]);
  78. removeActiveEle([...imgs]);
  79. setActiveEle2([...imgs], 4);
  80. setActiveEle2([...btns], 4);
  81. }
  82. } else if (ev.target.className == "next") {
  83. if (nextindex != 5) {
  84. //没到尽头,直接显示nextindex
  85. removeActiveEle([...btns]);
  86. removeActiveEle([...imgs]);
  87. setActiveEle2([...imgs], nextindex);
  88. setActiveEle2([...btns], nextindex);
  89. } else if (nextindex == 5) {
  90. //到尽头,直接跳转另一端的尽头
  91. removeActiveEle([...btns]);
  92. removeActiveEle([...imgs]);
  93. setActiveEle2([...imgs], 1);
  94. setActiveEle2([...btns], 1);
  95. }
  96. }
  97. })
  98. );
  99. //要求3. 鼠标事件,当鼠标移出轮播图区域时,图片以两秒的间隔进行轮播
  100. //思考:自动事件setInterval,图片第2秒跳转,类似于每2秒点击一次后一张的按钮事件
  101. //定时器
  102. let clock = null;
  103. //定义点击事件类型
  104. const clickEvent = new Event("click");
  105. //获取容器区域
  106. const container = document.qureySelector(".container");
  107. //点击对象
  108. const autonext = document.querySelector(".skip .next");
  109. //鼠标移出就开始定时轮播图片,定义start方法定时方法
  110. function start(){
  111. clock = setInteval(function(){
  112. //每2秒需要触发一次的事件类型为点击事件类型
  113. autonext.dispatchEvent(clickEvent);
  114. },2000);
  115. }
  116. //鼠标移出就停止定时器
  117. function stop(){
  118. clearInterval(clock);
  119. }
  120. //最后,将事件添加到容器对应的鼠标移出onmouseout和鼠标移入onmouerover事件监听器中
  121. container.addEventListener("mouseout",stop);
  122. container.addEventListener("mouseover",start);
Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post