• 【JavaScript】回调地狱以及网页轮播图底层分析


    🍈作者简介:大家好,我是亦世凡华、渴望知识储备自己的一名在校大学生

    🍇个人主页:亦世凡华、的博客

    🍓系列专栏:JavaScript专栏

    🥝推荐一款模拟面试刷题神器🔥:点击跳转进入网站

    目录

    🏍️回调地狱

    🍇具体分析

    🍈完整代码

    🏃网页轮播图

    🍉制作轮播图的空间盒子,用来存放图片

    🍊点击小圆圈可以播放相应的图片

    🍋鼠标不点击,轮播图会自动播放

    🍌完整代码


    🏍️回调地狱

    🍇具体分析

    根据上文动画函数的讲解,今天更近一步加深对回调函数的使用

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. <style>
    9. div {
    10. width: 200px;
    11. height: 200px;
    12. background: #f00;
    13. margin-top: 30px;
    14. position: absolute;
    15. }
    16. style>
    17. head>
    18. <body>
    19. <button>测试按钮button>
    20. <div>div>
    21. body>
    22. html>

    通过页面的内容,我想让盒子一次性实现向左移动然后变宽然后变高然后向下移动然后向上移动,然后向左移动。。。 如何做???,这里我们就需要借助回调函数不断调用定时器移动,通俗点讲,我们讲多个回调函数一起使用称为“回调地狱”。

    写JS第一步通常就是获取DOM元素,但是接下来的回调函数如何书写,请看如下代码及注释:

    现在分别对代码里面的参数进行讲解:

    move参数:

    * obj:要执行动画的对象

    * attr:要执行动画的样式

    * target:执行动画的目标位置

    * speed:移动的速度(正数向右移,负数向左移)

    * callback:回调函数,这个函数将会在动画执行完毕以后执行

    getStyle参数:

    * obj:要获取样式的元素

    * name:要获取的样式名

    定时器书写完毕,我们开始调用move函数,可以看到move里面的callback回调函数里面在嵌套move,接着在回调函数里面在嵌套move,不停的在callback里面嵌套函数,达到连续的动画效果,称为“回调函数”,可以看一下效果,如下:

    1. btn.addEventListener('click', function () {
    2. move(div, "left", 300, 10, function () {
    3. move(div,"width",500,10,function() {
    4. move(div,"height",300,10,function(){
    5. move(div,"bottom",100,10,function(){
    6. move(div,"top",100,10,function(){
    7. move(div,"left",-200,10,function(){})
    8. })
    9. })
    10. })
    11. })
    12. })
    13. })

    通过画面可以看到非常丝滑的动画效果,在这我们就要思考一下,是否可以把这个动画函数封装在一个JS文件里,当我们想要实现动画效果时直接调用动画函数就可以了,答案是“可行的”。这样便于了代码的书写,大大提高了编程效率。接下来通过一个典型案例,在进行动画函数的学习。

    🍈完整代码

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. <style>
    9. div {
    10. width: 200px;
    11. height: 200px;
    12. background: #f00;
    13. margin-top: 30px;
    14. position: absolute;
    15. }
    16. style>
    17. head>
    18. <body>
    19. <button>测试按钮button>
    20. <div>div>
    21. <script>
    22. var btn = document.querySelector('button')
    23. var div = document.querySelector('div')
    24. function move (obj, attr, target, speed, callback) {
    25. // 关闭上一个定时器
    26. clearInterval(obj.timer);
    27. // 获取元素当前位置
    28. var current = parseInt(getStyle(obj, attr));
    29. // 判断速度的正负值
    30. if (current > target) {
    31. // 此时速度应为负值
    32. speed = -speed;
    33. }
    34. // 开启一个定时器,用来执行动画效果
    35. // 向执行动画的对象添加一个timer属性,用来保存它自己的定时器
    36. obj.timer = setInterval(function () {
    37. // 获取目标原来的left值
    38. var oldValue = parseInt(getStyle(obj, attr));
    39. // 在旧值的基础上增加
    40. var newValue = oldValue + speed;
    41. /*
    42. 向左移动时,需要判断newValue是否小于target
    43. 向右移动时,需要判断newValue是否大于target
    44. */
    45. if ((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
    46. newValue = target;
    47. }
    48. // 将新值赋予目标
    49. obj.style[attr] = newValue + 'px';
    50. // 当元素移动到target时,停止执行动画
    51. if (newValue == target) {
    52. // 达到目标关闭定时器
    53. clearInterval(obj.timer);
    54. // 动画执行完毕调用回调函数 callback
    55. callback && callback();
    56. }
    57. }, 30);
    58. }
    59. function getStyle (obj, name) {
    60. if (window.getComputedStyle) {
    61. // 正常浏览器的方式,具有getComputedStyle()方法
    62. return getComputedStyle(obj, null)[name];
    63. } else {
    64. // IE8的方式,没有getComputedStyle()方法
    65. return obj.currentStyle[name];
    66. }
    67. }
    68. btn.addEventListener('click', function () {
    69. move(div, "left", 300, 10, function () {
    70. move(div,"width",500,10,function() {
    71. move(div,"height",300,10,function(){
    72. move(div,"bottom",100,10,function(){
    73. move(div,"top",100,10,function(){
    74. move(div,"left",-200,10,function(){})
    75. })
    76. })
    77. })
    78. })
    79. })
    80. })
    81. script>
    82. body>
    83. html>

    🏃网页轮播图

    轮播图也称为焦点图,是网页中比较常见的特效,今天做一下这个典型案例。

    🍉制作轮播图的空间盒子,用来存放图片

    我们可以根据自己的喜好设置自己轮播图的相关样式,这里就就需要借助HTML和CSS了,讲真HTML和CSS是重点基础,如果这两个没学好,是制作不出自己想要的样式,更别提后面的JS以及相关框架了,基础才是最重要的。

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. <style>
    9. *{
    10. margin: 0;
    11. padding: 0;
    12. }
    13. /* 设置outer样式 */
    14. #outer{
    15. /* 设置宽高 */
    16. width: 820px;
    17. height: 452px;
    18. /* 居中 */
    19. margin: 50px auto;
    20. /* 设置背景颜色 */
    21. background-color: #008c8c;
    22. /* 设置padding */
    23. padding: 10px 0;
    24. /* 开启相对定位 */
    25. position: relative;
    26. /* 溢出隐藏 */
    27. overflow: hidden;
    28. }
    29. /* 设置imgList */
    30. #imgList{
    31. /* 去除项目符号 */
    32. list-style: none;
    33. /* 设置ul宽度 */
    34. /* width: 3280px; */
    35. /* 开启绝对定位 */
    36. position: absolute;
    37. /* 设置偏移量,每向左移动820px 就会显示下一张图片 */
    38. }
    39. /* 设置li */
    40. #imgList li{
    41. /* 设置浮动 */
    42. float: left;
    43. /* 设置左右外边距 */
    44. margin: 0 10px;
    45. }
    46. /* 设置导航按钮 */
    47. .navDiv{
    48. /* 开启绝对定位 */
    49. position: absolute;
    50. /* 设置位置 */
    51. bottom: 20px;
    52. /* left: 35%; */
    53. }
    54. .navDiv a{
    55. /* 设置浮动,浮动之后,行内元素就能设置宽高 */
    56. float: left;
    57. /* 设置宽高 */
    58. width: 25px;
    59. height: 25px;
    60. /* 设置背景颜色 */
    61. background-color: #f00;
    62. /* 设置左右外边距 */
    63. margin: 0 15px;
    64. /* 设置半透明 */
    65. opacity: .5;
    66. /* 设置圆角 */
    67. border-radius: 50%;
    68. }
    69. /* 设置鼠标移入效果 */
    70. .navDiv a:hover{
    71. background-color: green;
    72. }
    73. style>
    74. head>
    75. <body>
    76. <div id="outer">
    77. <ul id="imgList">
    78. <li><img src="./01.jpeg">li>
    79. <li><img src="./02.jpeg">li>
    80. <li><img src="./03.jpeg">li>
    81. <li><img src="./04.jpeg">li>
    82. <li><img src="./01.jpeg">li>
    83. ul>
    84. <div class="navDiv">
    85. <a href="javascript:;">a>
    86. <a href="javascript:;">a>
    87. <a href="javascript:;">a>
    88. <a href="javascript:;">a>
    89. div>
    90. div>
    91. body>
    92. html>

     

    这里需要注意两点

    轮播图的按钮是要通过JS来居中,因为如果借助CSS居中,就会写死,后期添加图片又要重新设置。

    javascript:;是一个伪协议,加在超级链接上就可以防止 链接跳转,从而可以给链接JS上写自己想执行的代码。javascript:void(0) 表示一个死链接,执行空事件。

    🍊点击小圆圈可以播放相应的图片

    通过JS书写动态给按钮进行居中,并设置一个点击事件,来进行图片的切换并且按钮样式虽图片的变化而变化,这里借用了“排他思想”,先干掉所有人,然后保留自己人。

    🍋鼠标不点击,轮播图会自动播放

    自动播放就涉及动画函数了,根据上文的回调地狱的讲解,将动画函数move进行封装。如下:

    1. function move(obj,attr,target,speed,callback){
    2. // 关闭上一个定时器
    3. clearInterval(obj.timer);
    4. // 获取元素当前位置
    5. var current = parseInt(getStyle(obj,attr));
    6. // 判断速度的正负值
    7. if(current > target){
    8. // 此时速度应为负值
    9. speed = -speed;
    10. }
    11. // 开启一个定时器,用来执行动画效果
    12. // 向执行动画的对象添加一个timer属性,用来保存它自己的定时器
    13. obj.timer = setInterval(function(){
    14. // 获取目标原来的left值
    15. var oldValue = parseInt(getStyle(obj,attr));
    16. // 在旧值的基础上增加
    17. var newValue = oldValue + speed;
    18. /*
    19. 向左移动时,需要判断newValue是否小于target
    20. 向右移动时,需要判断newValue是否大于target
    21. */
    22. if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)){
    23. newValue = target;
    24. }
    25. // 将新值赋予目标
    26. obj.style[attr] = newValue + 'px';
    27. // 当元素移动到target时,停止执行动画
    28. if(newValue == target){
    29. // 达到目标关闭定时器
    30. clearInterval(obj.timer);
    31. // 动画执行完毕调用回调函数 callback
    32. callback && callback();
    33. }
    34. },30);
    35. }
    36. function getStyle(obj,name){
    37. if(window.getComputedStyle){
    38. // 正常浏览器的方式,具有getComputedStyle()方法
    39. return getComputedStyle(obj,null)[name];
    40. }else{
    41. // IE8的方式,没有getComputedStyle()方法
    42. return obj.currentStyle[name];
    43. }
    44. }

    接下里通过引入move函数实现动画效果。

    1. <script src="./move.js">script>

    可以看到代码中,我们设计了一个定时器实现自动切换图片,并设计在点击函数中关闭定时器,这样就不会出现点击事件和自动播放发生冲突,造成图片的怪异播放现象。

    🍌完整代码

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. <style>
    9. *{
    10. margin: 0;
    11. padding: 0;
    12. }
    13. /* 设置outer样式 */
    14. #outer{
    15. /* 设置宽高 */
    16. width: 820px;
    17. height: 452px;
    18. /* 居中 */
    19. margin: 50px auto;
    20. /* 设置背景颜色 */
    21. background-color: #008c8c;
    22. /* 设置padding */
    23. padding: 10px 0;
    24. /* 开启相对定位 */
    25. position: relative;
    26. /* 溢出隐藏 */
    27. overflow: hidden;
    28. }
    29. /* 设置imgList */
    30. #imgList{
    31. /* 去除项目符号 */
    32. list-style: none;
    33. /* 设置ul宽度 */
    34. /* width: 3280px; */
    35. /* 开启绝对定位 */
    36. position: absolute;
    37. /* 设置偏移量,每向左移动820px 就会显示下一张图片 */
    38. }
    39. /* 设置li */
    40. #imgList li{
    41. /* 设置浮动 */
    42. float: left;
    43. /* 设置左右外边距 */
    44. margin: 0 10px;
    45. }
    46. /* 设置导航按钮 */
    47. .navDiv{
    48. /* 开启绝对定位 */
    49. position: absolute;
    50. /* 设置位置 */
    51. bottom: 20px;
    52. /* left: 35%; */
    53. }
    54. .navDiv a{
    55. /* 设置浮动,浮动之后,行内元素就能设置宽高 */
    56. float: left;
    57. /* 设置宽高 */
    58. width: 25px;
    59. height: 25px;
    60. /* 设置背景颜色 */
    61. background-color: #f00;
    62. /* 设置左右外边距 */
    63. margin: 0 15px;
    64. /* 设置半透明 */
    65. opacity: .5;
    66. /* 设置圆角 */
    67. border-radius: 50%;
    68. }
    69. /* 设置鼠标移入效果 */
    70. .navDiv a:hover{
    71. background-color: green;
    72. }
    73. style>
    74. <script>
    75. window.addEventListener('load',function(){
    76. // 获取ul标签
    77. var ul = document.querySelector('#imgList')
    78. // 获取ul下li的子元素的个数,并给ul动态赋予宽度值
    79. ul.style.width = ul.children.length * 820 + 'px';
    80. // 设置导航按钮动态居中
    81. var navDiv = document.querySelector('.navDiv');
    82. var outer = document.querySelector('#outer');
    83. navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth) / 2 + 'px';
    84. // 默认显示图片的索引
    85. var index = 0;
    86. // 获取所有的a
    87. var aAll = document.querySelector('.navDiv').querySelectorAll('a');
    88. // 设置默认选中效果
    89. aAll[index].style.backgroundColor = 'green';
    90. // 为所有超链接绑定响应函数
    91. for(var i = 0;ilength;i++){
    92. // 为每一个超链接都添加一个num属性
    93. aAll[i].num = i;
    94. // 为超链接绑定点击响应函数
    95. aAll[i].addEventListener('click',function(){
    96. //关闭自动切换的定时器
    97. clearInterval(stop);
    98. // 获取超链接的索引,并将其设置为index
    99. index = this.num;
    100. // 切换图片
    101. // imgList.style.left = -820*index + 'px';
    102. setA();
    103. move(imgList,"left",-820*index,20,function(){
    104. //动画执行完毕,开启自动切换
    105. autoChange();
    106. })
    107. })
    108. }
    109. // // 开启自动切换图片
    110. autoChange();
    111. // 创建一个方法用来选中a
    112. function setA(){
    113. // 判断当前索引是否是第一张
    114. if(index >= ul.children.length-1){
    115. // 则将index设置为0
    116. index = 0;
    117. // 此时显示最后一张图片,而最后一张图片和第一张一模一样
    118. // 通过CSS将最后一张切换成第一张
    119. imgList.style.left = 0 + 'px';
    120. }
    121. for(var i = 0;ilength;i++){
    122. aAll[i].style.backgroundColor = '';
    123. }
    124. // 创建点击时的颜色
    125. aAll[index].style.backgroundColor = 'green';
    126. }
    127. // 创建一个函数,用来开启自动切换图片
    128. // 定义一个自动切换的定时器的标识
    129. var stop;
    130. function autoChange(){
    131. // 开启一个定时器,用来定时切换图片
    132. stop = setInterval(function(){
    133. // 使索引自增
    134. index++;
    135. // 判断index的值
    136. index %= ul.children.length;
    137. // 执行动画来切换图片
    138. move(imgList,"left",-820*index,20,function(){
    139. // 设置导航点
    140. setA();
    141. })
    142. },3000);
    143. };
    144. })
    145. script>
    146. <script src="./tool.js">script>
    147. head>
    148. <body>
    149. <div id="outer">
    150. <ul id="imgList">
    151. <li><img src="./01.jpeg">li>
    152. <li><img src="./02.jpeg">li>
    153. <li><img src="./03.jpeg">li>
    154. <li><img src="./04.jpeg">li>
    155. <li><img src="./01.jpeg">li>
    156. ul>
    157. <div class="navDiv">
    158. <a href="javascript:;">a>
    159. <a href="javascript:;">a>
    160. <a href="javascript:;">a>
    161. <a href="javascript:;">a>
    162. div>
    163. div>
    164. body>
    165. html>

    🍃JavaScript的学习还是要以多练习为主,想要练习JavaScript的朋友,推荐可以去牛客网看一看,链接:牛客网 里面的IT题库内容很丰富,属于国内做的很好的了,最重要的是里面的资源是免费的,是课程+刷题+面经+求职+讨论区分享,一站式求职学习网站,感兴趣的可以去看看。

    呜呜~,原创不易。

  • 相关阅读:
    Nginx详解 五:反向代理
    分布式之业务高可用
    [正确重装docker] Win10 重装 Docker 提示 Exising installation is up to date 的正确姿势
    滴灌通运营模式遭质疑:是P2P,是套利,还是模式创新?
    UNIAPP day_05(9.3) Cookie、WebStorage、Session 和 Token的区别、uni-app最终部署
    (数字图像处理MATLAB+Python)第十一章图像描述与分析-第五、六节:边界描述和矩描述
    volatility, polarizability, viscosity, electronegativity & hydrogen bonding
    Invertible Image Signal Processing 可逆图像信号处理
    无法获取下载文件名的无奈之举
    麒麟 Kylin V10 一键安装 Oracle 11GR2 单机 ASM(231017)
  • 原文地址:https://blog.csdn.net/qq_53123067/article/details/126067318