博客列表 >简单设计案例:选项卡、图片懒加载、轮播图

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

我是贝壳
我是贝壳原创
2021年01月20日 23:10:52691浏览

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

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