博客列表 >JS原生态写法实现网页经典动画:选项卡|轮播图|懒加载

JS原生态写法实现网页经典动画:选项卡|轮播图|懒加载

幸福敲门的博客
幸福敲门的博客原创
2021年01月13日 16:13:55711浏览

一、选项卡

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>选项卡</title>
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. box-sizing: border-box;
  12. }
  13. a {
  14. text-decoration: none;
  15. color: #555;
  16. }
  17. a:hover {
  18. text-decoration: underline;
  19. color: red;
  20. }
  21. li {
  22. list-style: none;
  23. line-height: 1.6em;
  24. }
  25. li:hover {
  26. cursor: default;
  27. }
  28. .boxs {
  29. width: 300px;
  30. height: 300px;
  31. margin: 30px;
  32. background-color: #e6e6e6;
  33. display: flex;
  34. flex-direction: column;
  35. }
  36. .box {
  37. height: 36px;
  38. display: flex;
  39. }
  40. .box li {
  41. flex: auto;
  42. text-align: center;
  43. line-height: 36px;
  44. background-color: #fff;
  45. }
  46. .box li.active {
  47. background-color: #e6e6e6;
  48. }
  49. .box li:hover {
  50. cursor: pointer;
  51. }
  52. /* 默认所有选项卡只有一个显示,其它隐藏 */
  53. .lanmu{
  54. padding: 20px;
  55. display: none;
  56. overflow: hidden;
  57. text-overflow: ellipsis;
  58. white-space:nowrap;
  59. }
  60. .lanmu.active {
  61. display: block;
  62. }
  63. </style>
  64. </head>
  65. <body>
  66. <div class="boxs">
  67. <!-- 导航 -->
  68. <ul class="box">
  69. <li class="active" data-index="1">国内</li>
  70. <li data-index="2">国际</li>
  71. <li data-index="3">军事</li>
  72. <li data-index="4">财经</li>
  73. <li data-index="5">体育</li>
  74. </ul>
  75. <!-- details -->
  76. <ul data-index="1" class="lanmu active">
  77. <li><a href="">新疆铁路南通道作用显现....</a></li>
  78. <li><a href="">福建的第一次!</a></li>
  79. <li><a href="">快递从业者也能成“高级工程师”?....</a></li>
  80. <li><a href="">重庆人盼望下雪的心有多强烈?...</a></li>
  81. <li><a href="">快递从业者也能成“高级工程师”?....</a></li>
  82. <li><a href="">江苏南通:优化产业布局 护好长...</a></li>
  83. </ul>
  84. <ul data-index="2" class="lanmu">
  85. <li><a href="">外交部批驳蓬佩奥又双叒叕散布谎言....</a></li>
  86. <li><a href="">任期进入倒计时,蓬佩奥还在散播....</a></li>
  87. <li><a href="">沙漠中一处“神秘”村庄,白天出现晚上消失,当地人不..</a></li>
  88. <li><a href="">国外打出租车:上车要说“by meter”,否则可..</a></li>
  89. <li><a href="">防止特朗普启动核武器!这场谈话触及五角大.....</a></li>
  90. <li><a href="">白宫美女发言人“变脸” 网友:“化妆师集体.....</a></li>
  91. </ul>
  92. <ul data-index="3" class="lanmu">
  93. <li><a href="">俄专家呼吁复活“核幽灵”列车....</a></li>
  94. <li><a href="">印军多高官近期密集访问列城....</a></li>
  95. <li><a href="">超燃现场!多型靶弹精准打击目标</a></li>
  96. <li><a href="">穿越冰河 这些边防军人筑起钢铁....</a></li>
  97. <li><a href="">美军无人机午夜侦察南海 至上午8....</a></li>
  98. <li><a href="">中国海警舰艇编队1月13日在我钓.....</a></li>
  99. </ul>
  100. <ul data-index="4" class="lanmu">
  101. <li><a href="">别样的挂历小店</a></li>
  102. <li><a href="">丰台设50余个新冠肺炎疫苗临时接种点 已累计接...</a></li>
  103. <li><a href="">北京奇案:40幅珍贵画作在香港某画展上神秘消失</a></li>
  104. <li><a href="">美在耕耘——中国美术馆新年展”在京亮相</a></li>
  105. <li><a href="">加大备货、推惠民菜,北京商超、生鲜电商硬核保供...</a></li>
  106. <li><a href="">青岛新冠疫苗接种已达9万多人!市民将陆续免费接...</a></li>
  107. </ul>
  108. <ul data-index="5" class="lanmu">
  109. <li><a href="">山西汾酒股份胜苏州肯帝亚</a></li>
  110. <li><a href="">世界羽联更新防疫动态 内维尔等获准出战泰国赛</a></li>
  111. <li><a href="">我们始终在路上——人大网球队</a></li>
  112. <li><a href="">德国杯:勒沃库森胜法兰克福</a></li>
  113. <li><a href="">澳网资格赛现阳性病例!</a></li>
  114. <li><a href="">连救赛点!斯诺克大师赛颜丙涛6:5逆转罗伯逊进8强</a></li>
  115. </ul>
  116. </div>
  117. <script>
  118. // 事件代理
  119. const box = document.querySelector(".box");
  120. // 五个列表
  121. const lanmus = document.querySelectorAll(".lanmu");
  122. box.onclick = ev => {
  123. // 事件的绑定对象
  124. // console.log(ev.currentTarget);
  125. // 事件触发对象
  126. // console.log(ev.target);
  127. // 只需要二步:
  128. // 1. 清空之前所有处于激活状态的选项卡,并将当前点击对象激活
  129. [...box.children].forEach(lanmu => lanmu.classList.remove("active"));
  130. ev.target.classList.add("active");
  131. // 2. 根据自定义属性data-index找到对应的列表并显示出来
  132. // NodeList对象内置了forEach接口
  133. lanmus.forEach(lanmu => lanmu.classList.remove("active"));
  134. [...lanmus].filter(lanmu => lanmu.dataset.index === ev.target.dataset.index)[0].classList.add("active");
  135. };
  136. </script>
  137. </body>
  138. </html>

图示:
选项卡

二、轮播图

  1. <!DOCTYPE html>
  2. <html lang="en">
  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="" data-index="1" class="active" /></a>
  14. <a href=""><img src="banner/banner2.jpg" alt="" data-index="2" /></a>
  15. <a href=""><img src="banner/banner3.jpg" alt="" data-index="3" /></a>
  16. <a href=""><img src="banner/banner4.jpg" alt="" data-index="4" /></a>
  17. </nav>
  18. <!-- 2. 图片小按钮 -->
  19. <nav class="btns">
  20. <!-- 这些小按钮应该根据图片数量自动生成 -->
  21. <!-- <a href="" data-index="1" class="active"></a>
  22. <a href="" data-index="2"></a>
  23. <a href="" data-index="3"></a>
  24. <a href="" data-index="4"></a> -->
  25. </nav>
  26. <!-- 3. 翻页 -->
  27. <nav class="skip">
  28. <a href="#" class="prev">&lt;</a>
  29. <a href="#" class="next">&gt;</a>
  30. </nav>
  31. </div>
  32. <script>
  33. // 所有图片
  34. const imgs = document.querySelectorAll(".container > .imgs img");
  35. // 按钮组
  36. const btnGroup = document.querySelector(".container > .btns");
  37. // 翻页按钮
  38. const skip = document.querySelector(".container > .skip");
  39. skip.addEventListener("click", skipImg, false);
  40. // 单独写一个事件监听器,为后面的事件自动派发做准备
  41. skip.children[0].addEventListener("click", skipImg, false);
  42. // 将前后翻页,使用一个回调统一处理
  43. function skipImg(ev) {
  44. // 当前激活的图片,实际上这里用不到它,而应该用它的父级<a>来判断是否存在兄弟节点
  45. let currentImg = getActiveEle(imgs);
  46. // 当前图片组父元素,注意<img>父级是<a>,<a>的父级才是需要的父节点
  47. let parentEle = currentImg.parentElement.parentElement;
  48. // 当前元素的前一个兄弟节点:previousElementSibling;
  49. let prevEle = currentImg.parentElement.previousElementSibling;
  50. // 当前元素的下一个兄弟节点:nextElementSibling;
  51. let nextEle = currentImg.parentElement.nextElementSibling;
  52. // 第一张图片, firstElementChild第一个子元素
  53. let firstImg = parentEle.firstElementChild.firstElementChild;
  54. // 最后一张图片, firstElementChild, 最后一个子元素
  55. let lastImg = parentEle.lastElementChild.firstElementChild;
  56. let activeImg = currentImg;
  57. // 向前翻页
  58. if (ev.target.classList.contains("prev")) {
  59. // 如果存在前一张图片,就使用它,否则就使用最后一张图片来更新它,形成循环显示的效果
  60. let activeImg =
  61. prevEle !== null ? prevEle.firstElementChild : lastImg;
  62. // 使用激活元素来同步更新图片与按钮
  63. setActiveEle(activeImg.dataset.index);
  64. }
  65. // 向后翻页
  66. if (ev.target.classList.contains("next")) {
  67. // 如果不存在下一张图片,就用第一张图片更新它
  68. let activeImg =
  69. nextEle !== null ? nextEle.firstElementChild : firstImg;
  70. setActiveEle(activeImg.dataset.index);
  71. }
  72. }
  73. let timer = null;
  74. const slider = document.querySelector(".container");
  75. slider.addEventListener("mouseout", startTimer, false);
  76. slider.addEventListener("mouseover", clearTimer, false);
  77. // 启动定时器
  78. function startTimer() {
  79. // 创建自定义事件对象
  80. const clickEvent = new Event("click");
  81. timer = setInterval(
  82. () => skip.children[0].dispatchEvent(clickEvent),
  83. 2000
  84. );
  85. }
  86. // 清除定时器
  87. function clearTimer() {
  88. clearInterval(timer);
  89. }
  90. // 创建出一组与图片数量对应的小按钮
  91. function autoCreateBtns(ele, imgLength) {
  92. const frag = document.createDocumentFragment();
  93. for (let i = 0; i < imgLength; i++) {
  94. const a = document.createElement("a");
  95. a.href = "#";
  96. a.dataset.index = i + 1;
  97. if (i === 0) a.classList.add("active");
  98. frag.appendChild(a);
  99. }
  100. ele.appendChild(frag);
  101. }
  102. // 调用创建小按钮的函数
  103. autoCreateBtns(btnGroup, imgs.length);
  104. // 为刚刚生成的小按钮们添加点击事件
  105. const btns = document.querySelectorAll(".container > .btns > *");
  106. // 下面声明二个公共函数
  107. // 1. 获取激活的元素
  108. function getActiveEle(eles) {
  109. let activities = [...eles].filter(img => img.classList.contains("active"));
  110. return activities.shift();
  111. }
  112. // 2. 设置激活的元素,根据按钮索引更新正在显示的图片
  113. function setActiveEle(btnIndex) {
  114. [imgs, btns].forEach(arr => {
  115. // 将之前的状态全部重置到初始化(清空)
  116. getActiveEle(arr).classList.remove("active");
  117. arr.forEach(item => {
  118. if (item.dataset.index === btnIndex) {
  119. item.classList.add("active");
  120. }
  121. });
  122. });
  123. }
  124. // 为每一个小按钮添加事件
  125. btns.forEach(btn => btn.addEventListener("click", ev => setActiveEle(ev.target.dataset.index)));
  126. </script>
  127. </body>
  128. </html>

图示:
轮播图

三、懒加载图片

  1. body>
  2. <div class="container">
  3. <img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />
  4. <img src="images/temp.jpg" alt="" data-src="images/img-2.jpg" />
  5. <img src="images/temp.jpg" alt="" data-src="images/img-3.jpg" />
  6. <img src="images/temp.jpg" alt="" data-src="images/img-4.jpg" />
  7. <img src="images/temp.jpg" alt="" data-src="images/img-5.jpg" />
  8. <img src="images/temp.jpg" alt="" data-src="images/img-6.jpg" />
  9. <img src="images/temp.jpg" alt="" data-src="images/img-7.jpg" />
  10. <img src="images/temp.jpg" alt="" data-src="images/img-8.jpg" />
  11. <img src="images/temp.jpg" alt="" data-src="images/img-9.jpg" />
  12. <img src="images/temp.jpg" alt="" data-src="images/img-10.jpg" />
  13. <img src="images/temp.jpg" alt="" data-src="images/img-11.jpg" />
  14. <img src="images/temp.jpg" alt="" data-src="images/img-12.jpg" />
  15. <img src="images/temp.jpg" alt="" data-src="images/img-13.jpg" />
  16. <img src="images/temp.jpg" alt="" data-src="images/img-14.jpg" />
  17. <img src="images/temp.jpg" alt="" data-src="images/img-15.jpg" />
  18. <img src="images/temp.jpg" alt="" data-src="images/img-16.jpg" />
  19. <img src="images/temp.jpg" alt="" data-src="images/img-17.jpg" />
  20. <img src="images/temp.jpg" alt="" data-src="images/img-18.jpg" />
  21. <img src="images/temp.jpg" alt="" data-src="images/img-19.jpg" />
  22. <img src="images/temp.jpg" alt="" data-src="images/img-20.jpg" />
  23. <img src="images/temp.jpg" alt="" data-src="images/img-21.jpg" />
  24. <img src="images/temp.jpg" alt="" data-src="images/img-22.jpg" />
  25. <img src="images/temp.jpg" alt="" data-src="images/img-23.jpg" />
  26. <img src="images/temp.jpg" alt="" data-src="images/img-24.jpg" />
  27. <img src="images/temp.jpg" alt="" data-src="images/img-25.jpg" />
  28. <img src="images/temp.jpg" alt="" data-src="images/img-26.jpg" />
  29. <img src="images/temp.jpg" alt="" data-src="images/img-27.jpg" />
  30. <img src="images/temp.jpg" alt="" data-src="images/img-28.jpg" />
  31. <img src="images/temp.jpg" alt="" data-src="images/img-29.jpg" />
  32. <img src="images/temp.jpg" alt="" data-src="images/img-30.jpg" />
  33. <img src="images/temp.jpg" alt="" data-src="images/img-31.jpg" />
  34. <img src="images/temp.jpg" alt="" data-src="images/img-32.jpg" />
  35. <img src="images/temp.jpg" alt="" data-src="images/img-33.jpg" />
  36. <img src="images/temp.jpg" alt="" data-src="images/img-34.jpg" />
  37. <img src="images/temp.jpg" alt="" data-src="images/img-35.jpg" />
  38. <img src="images/temp.jpg" alt="" data-src="images/img-36.jpg" />
  39. <img src="images/temp.jpg" alt="" data-src="images/img-37.jpg" />
  40. <img src="images/temp.jpg" alt="" data-src="images/img-38.jpg" />
  41. <img src="images/temp.jpg" alt="" data-src="images/img-39.jpg" />
  42. <img src="images/temp.jpg" alt="" data-src="images/img-40.jpg" />
  43. <img src="images/temp.jpg" alt="" data-src="images/img-41.jpg" />
  44. <img src="images/temp.jpg" alt="" data-src="images/img-42.jpg" />
  45. <img src="images/temp.jpg" alt="" data-src="images/img-43.jpg" />
  46. <img src="images/temp.jpg" alt="" data-src="images/img-44.jpg" />
  47. <img src="images/temp.jpg" alt="" data-src="images/img-45.jpg" />
  48. <img src="images/temp.jpg" alt="" data-src="images/img-46.jpg" />
  49. <img src="images/temp.jpg" alt="" data-src="images/img-47.jpg" />
  50. <img src="images/temp.jpg" alt="" data-src="images/img-48.jpg" />
  51. <img src="images/temp.jpg" alt="" data-src="images/img-49.jpg" />
  52. <img src="images/temp.jpg" alt="" data-src="images/img-50.jpg" />
  53. <img src="images/temp.jpg" alt="" data-src="images/img-51.jpg" />
  54. <img src="images/temp.jpg" alt="" data-src="images/img-52.jpg" />
  55. <img src="images/temp.jpg" alt="" data-src="images/img-53.jpg" />
  56. <img src="images/temp.jpg" alt="" data-src="images/img-54.jpg" />
  57. <img src="images/temp.jpg" alt="" data-src="images/img-55.jpg" />
  58. <img src="images/temp.jpg" alt="" data-src="images/img-56.jpg" />
  59. <img src="images/temp.jpg" alt="" data-src="images/img-57.jpg" />
  60. <img src="images/temp.jpg" alt="" data-src="images/img-58.jpg" />
  61. <img src="images/temp.jpg" alt="" data-src="images/img-59.jpg" />
  62. <img src="images/temp.jpg" alt="" data-src="images/img-60.jpg" />
  63. <img src="images/temp.jpg" alt="" data-src="images/img-61.jpg" />
  64. <img src="images/temp.jpg" alt="" data-src="images/img-62.jpg" />
  65. <img src="images/temp.jpg" alt="" data-src="images/img-63.jpg" />
  66. <img src="images/temp.jpg" alt="" data-src="images/img-64.jpg" />
  67. <img src="images/temp.jpg" alt="" data-src="images/img-65.jpg" />
  68. <img src="images/temp.jpg" alt="" data-src="images/img-66.jpg" />
  69. <img src="images/temp.jpg" alt="" data-src="images/img-67.jpg" />
  70. <img src="images/temp.jpg" alt="" data-src="images/img-68.jpg" />
  71. <img src="images/temp.jpg" alt="" data-src="images/img-69.jpg" />
  72. <img src="images/temp.jpg" alt="" data-src="images/img-70.jpg" />
  73. </div>
  74. </body>
  75. <script>
  76. const imgs = document.querySelectorAll(".container img");
  77. const clientHeight = document.documentElement.clientHeight;
  78. window.addEventListener("scroll", layzyload);
  79. // load:页面加载完成自动执行
  80. window.addEventListener("load", layzyload);
  81. function layzyload() {
  82. // 滚动高度
  83. let scrollTop = document.documentElement.scrollTop;
  84. // 遍历图片并判断是否进入到了可视区
  85. imgs.forEach(img => {
  86. // 只要当前图片距离文档顶部的偏移量,小于可视区高度与滚动高度之间则表示进入到可视区,应该显示出来
  87. // clientHeight是可视区高度,这是一个固定的值,滚动高度是动态的
  88. if (img.offsetTop < clientHeight + scrollTop) {
  89. setTimeout(() => (img.src = img.dataset.src), 500);
  90. }
  91. });
  92. }
  93. </script>

图示:
懒加载

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