昨天学习到了JS特效部分,然后老师讲了旋转木马特效的实现,如上图。不过只是讲了通过点击箭头实现图片的切换,对于点击图片本身以及二者联动却是没有讲解。

  本着一颗追求完美的心,今天花费了一个中午终于将整个功能全部完善(死了太多脑细胞~~)。

  接下来直接进入主题哈~(主要讲解JS,所以对其中的HTML及CSS不做详细说明。)

  首先是HTML代码

  

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title>旋转木马轮播图</title>
  6. <link rel="stylesheet" href="css/css.css"/>
  7. </head>
  8. <body>
  9. <div class="wrap" id="wrap">
  10. <div class="slide" id="slide">
  11. <ul>
  12. <li><a href="#"><img src="data:images/slidepic1.jpg" alt=""/></a></li>
  13. <li><a href="#"><img src="data:images/slidepic2.jpg" alt=""/></a></li>
  14. <li><a href="#"><img src="data:images/slidepic3.jpg" alt=""/></a></li>
  15. <li><a href="#"><img src="data:images/slidepic4.jpg" alt=""/></a></li>
  16. <li><a href="#"><img src="data:images/slidepic5.jpg" alt=""/></a></li>
  17. </ul>
  18. <div class="arrow" id="arrow">
  19. <a href="javascript:;" class="prev" id="arrLeft"></a>
  20. <a href="javascript:;" class="next" id="arrRight"></a>
  21. </div>
  22. </div>
  23. </div>
  24. </body>
  25. </html>

    以下为CSS代码:

  1. blockquote, body, button, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, hr, input, legend, li, ol, p, pre, td, textarea, th, ul {
  2. margin:;
  3. padding: 0
  4. }
  5.  
  6. body, button, input, select, textarea {
  7. font: 12px/1.5 "Microsoft YaHei", "微软雅黑", SimSun, "宋体", sans-serif;
  8. color: #666;
  9. }
  10.  
  11. ol, ul {
  12. list-style: none
  13. }
  14.  
  15. a {
  16. text-decoration: none
  17. }
  18.  
  19. fieldset, img {
  20. border:;
  21. vertical-align: top;
  22. }
  23.  
  24. a, input, button, select, textarea {
  25. outline: none;
  26. }
  27.  
  28. /*以上为简单的初始化*/
  29.  
  30. a, button {
  31. cursor: pointer;
  32. }
  33.  
  34. .wrap {
  35. width: 1200px;
  36. margin: 100px auto;
  37. }
  38.  
  39. .slide {
  40. height: 500px;
  41. position: relative;
  42. }
  43.  
  44. .slide li {
  45. position: absolute;
  46. left: 200px;
  47. top:;
  48. }
  49.  
  50. .slide li img {
  51. width: 100%;
  52. }
  53.  
  54. .arrow {
  55. opacity:;
  56. position: absolute;
  57. top: 200px;
  58. z-index:;
  59. }
  60. .arrow .next{
  61. left: 1120px;
  62. }
  63. .prev, .next {
  64. width: 76px;
  65. height: 112px;
  66. position: absolute;
  67. top: 50%;
  68. margin-top: -56px;
  69. background: url(../images/prev.png) no-repeat;
  70. z-index:;
  71. }
  72.  
  73. .next {
  74. right:;
  75. background-image: url(../images/next.png);

  以下为JS代码:先说明一下整体的思路

  1、设置鼠标移入移出事件,显示图片中的左右两个箭头

  2、设置左右两个箭头的点击事件,通过点击箭头,实现配置单中的样式切换(因为获取图片所在的li是一个伪数组,无法使用数组的方法,所以图片的轮播实现主要是通过对配置单内元素索引的改变完成的。)

  3、设置点击li(也就是图片,后面统一写为li)标签实现点击的li出现在界面最前端。

  4、实现点击箭头后,点击li的联动,也就是无论点击箭头多少次,再次点击li后,也能将当前点击的li显示在界面最前端。

  5、实现点击li后,点击箭头的联动,也就是无论点击li后当前界面最前端的li是哪一个,再次点击箭头后,都能按照点击箭头的规则切换到当前li的下一个或上一个li。

  是不是有点啰嗦啊 0...0

  

  1. <script>
      (function(){//今天偶尔看到一篇问文章,其中说道用自调用函数封装自己的JS代码可以防止环境污染哈~好像还有其他很好的功能,还没有详细了解,这里就拿出来爽一下~
  2. var config = [
  3. {
  4. width: 400,
  5. top: 20,
  6. left: 50,
  7. opacity: 0.2,
  8. zIndex: 2
  9. },
  10. {
  11. width: 600,
  12. top: 70,
  13. left: 0,
  14. opacity: 0.8,
  15. zIndex: 3
  16. },
  17. {
  18. width: 800,
  19. top: 100,
  20. left: 200,
  21. opacity: 1,
  22. zIndex: 4
  23. },
  24. {
  25. width: 600,
  26. top: 70,
  27. left: 600,
  28. opacity: 0.8,
  29. zIndex: 3
  30. },
  31. {
  32. width: 400,
  33. top: 20,
  34. left: 750,
  35. opacity: 0.2,
  36. zIndex: 2
  37. }
  38. ];//config为一个配置单 规定了每张图片的大小位置层级透明度
  39. //获取元素
  40. var wrap = document.getElementById('wrap')
  41. var slide = document.getElementById('slide')
  42. var ul = slide.children[0]
  43. var lis = ul.children
  44. var arrow = document.getElementById('arrow')
  45. var arrLeft = document.getElementById('arrLeft')
  46. var arrRight = document.getElementById('arrRight')
  47. //4.3 因为要控制图片显示的频率,因此要等到每次图片正常切换完成才进行下一次图片切换,假设初始时图片切换完成 flag == true
  48. var flag = true, count = 2, cFlag = false //7.92 这里设置cFlag初始值为false
  49.  
  50. /**
  51. * 缓动改变样式的函数,先封装这个函数,后面进行配置单内的样式添加只需要调用这个函数就可以了。
  52. * @param tag 要改变的元素
  53. * @param json 一个对象,里面以属性保存要修改的样式
  54. * @param fn 传入函数,可以在第一次调用执行后,再执行传入的函数体内容
  55. */
  56. function perfectAnimate(tag, json, fn) {
  57. clearInterval(tag.timer)//首先清除定时器
  58. tag.timer = setInterval(function () {//新建一个setInterval,设置周期时间为18ms,这个数字不固定~
  59. var flag = true //这里运用了假设成立法
  60. for (var k in json) { //遍历传入的对象
  61. if (k == 'opacity') { //判断对象中保存的样式,如果为opacity,单独设置
  62. var leader = getStyle(tag, k) * 100 //这里获取opacity的初始值。这里使用的是下面获取样式的兼容函数。
                                     //乘100是因为JS小数计算存在精度问题。所以这里在下将其扩大100倍进行使用。
  63. var target = json[k] * 100  //这里取出opacity的目标值,也就是对象中的样式属性值
  64. var step = (target - leader) / 10; //这里用目标值减去初始值除以10达到缓动的目的(变速改变)
  65. step = step > 0 ? Math.ceil(step) : Math.floor(step);//这里也可以不使用这个判断,对step向上或向下保证最后的时候每次都能至少走1
  66. leader = leader + step; //初始值加上每次增加或减少的值
  67. tag.style[k] = leader / 100; //将值设置给opacity属性,当然别忘了把100除回来~
  68. } else if (k == 'zIndex') {
  69. tag.style[k] = json[k] //如果为zIndex 这时候就直接设置给样式就行了。
  70. } else {
  71. var leader = parseInt(getStyle(tag, k)) || 0 //当样式属性值为带单位的时候,这时候要进行一个取整去掉单位,同时为了防止没有初始值而默认为auto,使用一个短路操作
  72. var target = json[k]
  73. var step = (target - leader) / 10
  74. step = step > 0 ? Math.ceil(step) : Math.floor(step)
  75. leader = leader + step
  76. tag.style[k] = leader + 'px'
  77. }
  78. if (target != leader) {
  79. flag = false //这里只要有一个没有样式没有设置完成,假设便不成立,便不执行下面的清除
  80. }
  81. }
  82. if (flag) { //假设所有属性都设置完成,便清除定时器,节约空间
  83. clearInterval(tag.timer)
  84. // if ("function" == typeof fn) {
  85. // fn()
  86. // }
  87. fn && fn();//清除定时器后,可能会有需要的功能要在以上执行完成后执行,这里使用一个回调函数,
    //同样使用短路操作,防止没有传函数而报错。上面注释的与这个功能一样,只是更严谨,这个更简洁
  88. }
  89. }, 18)
  90. }
  91.  
  92. /**
  93. * 获取多个样式的方法的兼容性。current是IE自己的,不支持getComputedStyle
  94. * @param tag 是标签名
  95. * @param attr 是具体的某个样式的属性
  96. * @returns {*} 返回的是这个样式的属性值
  97. */
  98. function getStyle(tag, attr) {
  99. if (tag.currentStyle) {
  100. return tag.currentStyle[attr];
  101. } else {
  102. return getComputedStyle(tag, null)[attr];
  103. }
  104. }
  105.  
  106.   //以上准备工作做完,然后可以开始我们代码代码的书写了。
      //哎呀,好困呀~~还好后面的内容在我中午写的时候已经做好注释了,省了不少时间哇,哈哈哈哈....
      //建议以序号顺序进行阅读哈,虽然自我感觉挺详细的,但是可能存在某些表述不准确的地方,望谅解~毕竟这才是我的第二篇博客啦...

  107. /**
  108. * 1 封装函数,将config中的样式一一对应设置给li标签,因为后面会多次调用它
  109. */
  110. function change() {
  111. for (var i = 0; i < config.length; i++) {
  112. perfectAnimate(lis[i], config[i], function () {
  113. flag = true//4.6 这里在perfectAnimate函数中传入函数,赋值flag为true,因为这时候图片切换已经完成,可以进行下一次切换了。
  114. })
  115. }
  116. }
  1. //2 最开始的默认分布(也就是上图那个效果~),直接调用函数
  1. change() //3 设置移入移出事件,显示与隐藏箭头

  2. wrap.onmouseover = function () {
  3. perfectAnimate(arrow, {'opacity': 1})
  4. }
  5. wrap.onmouseout = function () {
  6. perfectAnimate(arrow, {'opacity': 0})
  7. }
  8.  
  9. /**
  10. *
  11. */
  12. function clearChangeConfig2() {
  13. if (cFlag) { //7.93 因为最开始点击箭头时,没有进行li的点击切换,不需要进行联动,只有点击过li后,再点击箭头才执行,可以
  14. // 使用cFlag作为判断条件
  15. cFlag = false //7.91 这里被调用是需要执行changeConfig1(this.index)里面的if判断,所以首先设置cFlag为false
  16. for (var i = 0; i < lis.length; i++) {
  17. //7.4 因为点击li后图片进行切换后,config中的元素又回到初始位置,与设置给li的并不相同,这时就需要
  18. // 将点击li时最后执行的changeConfig2(this.index),再退回到changeConfig1(this.index),要做到上一
  19. // 步,就需要找到当前点击的li的索引,因为当前点击的li肯定是设置有属性zIndex=4,并且其index属性保存了
  20. // 其索引值,所以通过这就可以找到需要的索引了。
  21. if (lis[i].style.zIndex == 4) {
  22. changeConfig1(lis[i].index)//7.5 找到索引后直接将config中元素的位置退回到changeConfig1(this.index)
  23. }
  24. }
  25. }
  26. }
  27.  
  28. function pushCount() {
  29. if (count <= config.length && count > 0) {
  30. count--
  31. } else {
  32. count = 4
  33. }
  34. }
  35. function unshiftCount() {
  36. if (count < config.length && count >= 0) {
  37. count++
  38. } else {
  39. count = 0
  40. }
  41. }
  42.  
  43. //4 添加右箭头点击事件
  44. arrRight.onclick = function () {
  45. if (flag) {//4.4 如果flag为true,即4.3假设成立,便执行下面的代码
  46. flag = false//4.5 给flag设置为false,使假设不成立,这时候只要没有改变flag值,点击事件源将不在执行这里的代码,不过此次下面代码依旧会执行
  47. clearChangeConfig2()//7.3 这里调用是为了点击li后,实现箭头的联动,具体看7.4
  48. config.push(config.shift())//4.1 点击后将第一个样式剪切到最后一个
  49. change()//4.2 通过调用函数,将新生成的config元素一一对应设置给li标签

      //7.0 点击箭头后,实现与li点击联动,每次点击右箭头count值都会自减一次,count初始值为2.小于0后直接赋值为4
  1. //count的值对应的是每次进行切换后,zIndex值为4的元素在config中的索引值,并以此为初始值(取代6.5设置的2)——界面最前端的配置属性,使得点击li时正常切换
  1. pushCount() } } //5 添加左箭头点击事件
  2. arrLeft.onclick = function () {
  3. if (flag) {
  4. flag = false
  5. clearChangeConfig2()
  6. config.unshift(config.pop())//5.1 点击后将最后一个样式剪切到第一个
  7. change() //5.2 通过调用函数,将新生成的config元素一一对应设置给li标签
  8. unshiftCount()//7.1 将箭头点击与li点击联动,每次点击左箭头count值都会自增一次,count初始值为2.大于4后直接赋值为0
  9. }
  10.  
  11. }
  12. /**
  13. * 6.3 根据当前点击的li的索引值,给li设置config内元素中的属性
  14. * @param i 当前点击li的索引值
  15. */
  16. function changeConfig1(i) {
  17. //6.5 未设置联动时,count位置应该是数字2,即最开始时zIndex值为4的config元素对应的索引,改变的中心思想为:zIndex中值为4的config元素(界面最前端的配置属性)
  1. // 总是设置给当前的点击的li,保持二者索引一致(count先不管)
  2. //6.6 然后进行判断,如果当前li的索引值小于等于2
  3. //7.2 这时将count作为条件依据,等同于以zIndex值为4的元素的索引为依据
  4. if (i <= count) {
  5. for (var i = i; i < count; i++) {
  6. config.push(config.shift())//6.7 那么根据其索引值进行0位config元素的剪切,直到zIndex值为4的config元素对应的索引与当前点击的li的索引一致
  7. if (cFlag == false) {//7.8 又因为点击li时,config元素与li进行对应设置后,又会回到初始位置,不会影响到count的变化
  8. //所以点击li时调用这个函数不能执行这个if判断,这里再次使用假设成立法,假设cFlag为false时执行if判断成立
  9. pushCount()//7.6 因为将config中元素的位置改为正常的后,zIndex=4的元素的索引又会发生变化,所以这时count也要跟着变化
  10. i--//7.7 这里的count为--,所以i值也要--才能保证count自减的次数与循环执行次数一致(即与config元素剪切的次数一致,即保证count的值总是配置单中zIndex=4的元素的索引)
  11. }
  12. }
  13. } else {
  14. for (var i = i; i > count; i--) {
  15. config.unshift(config.pop())//6.8 如果大于2,那么根据其索引值进行索引为4的config元素的剪切,直到zIndex值为4的config元素对应的索引与当前点击的li的索引一致
  16. if (cFlag == false) {
  17. unshiftCount()
  18. i++
  19. }
  20. }
  21. }
  22.  
  23. }
  24.  
  25. function changeConfig2(i) {
  26. if (i <= count) {
  27. for (var i = i; i < count; i++) {
  28. config.unshift(config.pop())
  29. if (cFlag == false) {
  30. pushCount()
  31. }
  32. }
  33. } else {
  34. for (var i = i; i > count; i--) {
  35. config.push(config.shift())
  36. if (cFlag == false) {
  37. unshiftCount()
  38. }
  39. }
  40. }
  41. }
  42.  
  43. //6 遍历lis,给li设置点击事件
  44. for (var i = 0; i < lis.length; i++) {
  45. lis[i].index = i//6.4 以lis[i]的自定义属性index保存其索引值
  46. lis[i].onclick = function () {//6.1 添加事件
  47. cFlag = true //7.9 点击li时执行changeConfig1(this.index)之前将cFlag赋值true,即不执行它里面的if判断
  48. changeConfig1(this.index)//6.2 点击li后将zIndex值为4的config元素添加给当前点击的li,其他元素依次挪动。
  49. change()//6.9通过调用函数,将修改后的config内的元素属性一一对应设置给li
  50. changeConfig2(this.index)//6.91 在第6.2步中,zIndex值为4config元素进行过剪切可能已经不在索引为2的位置了,这时后我们再进行与6.2步中相反的操作
  51. // 将config中的元素位置回归到初始状态,但是并不设置给li.
  52. }
  53. }
      }())
  54. </script>

  最后本着负责的态度,还是认真对着上面的文字检查了20分钟,确保在自己水平内将问题讲清楚——可是、好像还是不够太具体化...

   看来只能等以后的理解更加透彻后,再对本文进行修改了。

          ——BY:骑士与魔王(我微博也是这个名字哈,里面还有自己之前玩微博时写的图文小说,《骑士与魔王》,可惜太监啦,哈哈哈哈)

Javascript学习记录——原生JS实现旋转木马特效的更多相关文章

  1. JavaScript学习记录三

    title: JavaScript学习记录三 toc: true date: 2018-09-14 23:51:22 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  2. JavaScript学习记录二

    title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  3. JavaScript学习记录四

    title: JavaScript学习记录四 toc: true date: 2018-09-16 20:31:22 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  4. JavaScript学习记录一

    title: JavaScript学习记录一 toc: true date: 2018-09-11 18:26:52 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  5. 原生js实现架子鼓特效

    这是代码完成的效果,按下abcd会出现对应的架子鼓音乐的效果. 简单的介绍下代码思路,html和css部分就不多说了. 重要的是js部分. 大致是这样的, 首先获取到所有的按钮为一个数组,然后遍历整个 ...

  6. 原生JS实现旋转木马轮播图特效

    大概是这个样子: 首先来简单布局一下(emm...随便弄一下吧,反正主要是用js来整的) <!DOCTYPE html> <html lang="en"> ...

  7. 诶西,JavaScript学习记录。。。。。。

    由于大学课程缘故,老师巨爱叫人问问题,还记分呢,随便记录一下Js的学习情况,以后复习什么的也比较方便吧...... 开始咯,就按照C语言学习那样的方法来吧! ===================== ...

  8. 原生JS实现"旋转木马"效果的图片轮播插件

    一.写在最前面 最近都忙一些杂七杂八的事情,复习软考.研读经典...好像都好久没写过博客了... 我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的, ...

  9. JavaScript学习记录总结(四)——js函数的特殊性

    <script type="text/javascript">  //当局部变量与全局变量 重名的时候   var v="全局变量";//定义全局变 ...

随机推荐

  1. Swift 之模糊效果(毛玻璃效果,虚化效果)的实现

    前言: 之前项目中有用到过Objective-C的的模糊效果,感觉很是不错,而且iOS8之后官方SDK也直接提供了可以实现毛玻璃效果的三个类:UIBlurEffect.UIVibrancyEffect ...

  2. IOS UIAppLocation 单例模式

    UIApplocation * app=[UIApplocation shareapplocation]; UIAppLocation 只能被初始化一次. 一个程序中只能被创建一次,称为单例模式. 单 ...

  3. 安装zabbix-3.0.3+nginx-1.10.1+php-5.6.22

    好久没有接触监控类的软件了,今天抽空搭建了下最新的版本 首先系统环境 zabbix-server-1 192.168.11.11   centos6.7 mysql-server    192.168 ...

  4. Where product development should start

    We all need to know our customers in order to create products they’ll actually buy. This is why the  ...

  5. Python 爬虫2——环境配置

    关于环境配置的操作,其实非常简单,假如不使用第三方的框架的话,只需要安装Python即可完成后续的操作. 一.Python的安装和配置: windows系统的安装配置过程如下,假如是Mac系统,可参考 ...

  6. AmazeUI 框架知识点-组件

    1.Badge 默认:添加 .am-badge class 到 <div> 或者 <span> 元素. 圆角:在默认样式的基础上添加 .am-radius class. 椭圆: ...

  7. [ios] 定位报错Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"

    Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error ...

  8. 关于iOS后台问题( 一 )(ios后台刷新,后台定位,后台下载,真后台)

    关于iOS的后台,以下引用一些文段进行一下脑补,请同学们大致看一下,有个基础,原文出处 -------------------------------------------------------- ...

  9. 定时任务crontab 例子

    查看定时任务格式 [root@centos ~]# vim /etc/crontab 1 SHELL=/bin/bash 2 PATH=/sbin:/bin:/usr/sbin:/usr/bin 3 ...

  10. 工作中那些提高你效率的神器(第一篇)_Everything

    引言 无论是工作还是科研,我们都希望工作既快又好,然而大多数时候却迷失在繁杂的重复劳动中,久久无法摆脱繁杂的事情. 你是不是曾有这样一种想法:如果我有哆啦A梦的口袋,只要拿出神奇道具就可解当下棘手的问 ...