Javascript学习记录——原生JS实现旋转木马特效
昨天学习到了JS特效部分,然后老师讲了旋转木马特效的实现,如上图。不过只是讲了通过点击箭头实现图片的切换,对于点击图片本身以及二者联动却是没有讲解。
本着一颗追求完美的心,今天花费了一个中午终于将整个功能全部完善(死了太多脑细胞~~)。
接下来直接进入主题哈~(主要讲解JS,所以对其中的HTML及CSS不做详细说明。)
首先是HTML代码
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8">
- <title>旋转木马轮播图</title>
- <link rel="stylesheet" href="css/css.css"/>
- </head>
- <body>
- <div class="wrap" id="wrap">
- <div class="slide" id="slide">
- <ul>
- <li><a href="#"><img src="data:images/slidepic1.jpg" alt=""/></a></li>
- <li><a href="#"><img src="data:images/slidepic2.jpg" alt=""/></a></li>
- <li><a href="#"><img src="data:images/slidepic3.jpg" alt=""/></a></li>
- <li><a href="#"><img src="data:images/slidepic4.jpg" alt=""/></a></li>
- <li><a href="#"><img src="data:images/slidepic5.jpg" alt=""/></a></li>
- </ul>
- <div class="arrow" id="arrow">
- <a href="javascript:;" class="prev" id="arrLeft"></a>
- <a href="javascript:;" class="next" id="arrRight"></a>
- </div>
- </div>
- </div>
- </body>
- </html>
以下为CSS代码:
- 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 {
- margin:;
- padding: 0
- }
- body, button, input, select, textarea {
- font: 12px/1.5 "Microsoft YaHei", "微软雅黑", SimSun, "宋体", sans-serif;
- color: #666;
- }
- ol, ul {
- list-style: none
- }
- a {
- text-decoration: none
- }
- fieldset, img {
- border:;
- vertical-align: top;
- }
- a, input, button, select, textarea {
- outline: none;
- }
- /*以上为简单的初始化*/
- a, button {
- cursor: pointer;
- }
- .wrap {
- width: 1200px;
- margin: 100px auto;
- }
- .slide {
- height: 500px;
- position: relative;
- }
- .slide li {
- position: absolute;
- left: 200px;
- top:;
- }
- .slide li img {
- width: 100%;
- }
- .arrow {
- opacity:;
- position: absolute;
- top: 200px;
- z-index:;
- }
- .arrow .next{
- left: 1120px;
- }
- .prev, .next {
- width: 76px;
- height: 112px;
- position: absolute;
- top: 50%;
- margin-top: -56px;
- background: url(../images/prev.png) no-repeat;
- z-index:;
- }
- .next {
- right:;
- 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
- <script>
(function(){//今天偶尔看到一篇问文章,其中说道用自调用函数封装自己的JS代码可以防止环境污染哈~好像还有其他很好的功能,还没有详细了解,这里就拿出来爽一下~- var config = [
- {
- width: 400,
- top: 20,
- left: 50,
- opacity: 0.2,
- zIndex: 2
- },
- {
- width: 600,
- top: 70,
- left: 0,
- opacity: 0.8,
- zIndex: 3
- },
- {
- width: 800,
- top: 100,
- left: 200,
- opacity: 1,
- zIndex: 4
- },
- {
- width: 600,
- top: 70,
- left: 600,
- opacity: 0.8,
- zIndex: 3
- },
- {
- width: 400,
- top: 20,
- left: 750,
- opacity: 0.2,
- zIndex: 2
- }
- ];//config为一个配置单 规定了每张图片的大小位置层级透明度
- //获取元素
- var wrap = document.getElementById('wrap')
- var slide = document.getElementById('slide')
- var ul = slide.children[0]
- var lis = ul.children
- var arrow = document.getElementById('arrow')
- var arrLeft = document.getElementById('arrLeft')
- var arrRight = document.getElementById('arrRight')
- //4.3 因为要控制图片显示的频率,因此要等到每次图片正常切换完成才进行下一次图片切换,假设初始时图片切换完成 flag == true
- var flag = true, count = 2, cFlag = false //7.92 这里设置cFlag初始值为false
- /**
- * 缓动改变样式的函数,先封装这个函数,后面进行配置单内的样式添加只需要调用这个函数就可以了。
- * @param tag 要改变的元素
- * @param json 一个对象,里面以属性保存要修改的样式
- * @param fn 传入函数,可以在第一次调用执行后,再执行传入的函数体内容
- */
- function perfectAnimate(tag, json, fn) {
- clearInterval(tag.timer)//首先清除定时器
- tag.timer = setInterval(function () {//新建一个setInterval,设置周期时间为18ms,这个数字不固定~
- var flag = true //这里运用了假设成立法
- for (var k in json) { //遍历传入的对象
- if (k == 'opacity') { //判断对象中保存的样式,如果为opacity,单独设置
- var leader = getStyle(tag, k) * 100 //这里获取opacity的初始值。这里使用的是下面获取样式的兼容函数。
//乘100是因为JS小数计算存在精度问题。所以这里在下将其扩大100倍进行使用。- var target = json[k] * 100 //这里取出opacity的目标值,也就是对象中的样式属性值
- var step = (target - leader) / 10; //这里用目标值减去初始值除以10达到缓动的目的(变速改变)
- step = step > 0 ? Math.ceil(step) : Math.floor(step);//这里也可以不使用这个判断,对step向上或向下保证最后的时候每次都能至少走1
- leader = leader + step; //初始值加上每次增加或减少的值
- tag.style[k] = leader / 100; //将值设置给opacity属性,当然别忘了把100除回来~
- } else if (k == 'zIndex') {
- tag.style[k] = json[k] //如果为zIndex 这时候就直接设置给样式就行了。
- } else {
- var leader = parseInt(getStyle(tag, k)) || 0 //当样式属性值为带单位的时候,这时候要进行一个取整去掉单位,同时为了防止没有初始值而默认为auto,使用一个短路操作
- var target = json[k]
- var step = (target - leader) / 10
- step = step > 0 ? Math.ceil(step) : Math.floor(step)
- leader = leader + step
- tag.style[k] = leader + 'px'
- }
- if (target != leader) {
- flag = false //这里只要有一个没有样式没有设置完成,假设便不成立,便不执行下面的清除
- }
- }
- if (flag) { //假设所有属性都设置完成,便清除定时器,节约空间
- clearInterval(tag.timer)
- // if ("function" == typeof fn) {
- // fn()
- // }
- fn && fn();//清除定时器后,可能会有需要的功能要在以上执行完成后执行,这里使用一个回调函数,
//同样使用短路操作,防止没有传函数而报错。上面注释的与这个功能一样,只是更严谨,这个更简洁- }
- }, 18)
- }
- /**
- * 获取多个样式的方法的兼容性。current是IE自己的,不支持getComputedStyle
- * @param tag 是标签名
- * @param attr 是具体的某个样式的属性
- * @returns {*} 返回的是这个样式的属性值
- */
- function getStyle(tag, attr) {
- if (tag.currentStyle) {
- return tag.currentStyle[attr];
- } else {
- return getComputedStyle(tag, null)[attr];
- }
- }
- //以上准备工作做完,然后可以开始我们代码代码的书写了。
//哎呀,好困呀~~还好后面的内容在我中午写的时候已经做好注释了,省了不少时间哇,哈哈哈哈....
//建议以序号顺序进行阅读哈,虽然自我感觉挺详细的,但是可能存在某些表述不准确的地方,望谅解~毕竟这才是我的第二篇博客啦...- /**
- * 1 封装函数,将config中的样式一一对应设置给li标签,因为后面会多次调用它
- */
- function change() {
- for (var i = 0; i < config.length; i++) {
- perfectAnimate(lis[i], config[i], function () {
- flag = true//4.6 这里在perfectAnimate函数中传入函数,赋值flag为true,因为这时候图片切换已经完成,可以进行下一次切换了。
- })
- }
- }
- //2 最开始的默认分布(也就是上图那个效果~),直接调用函数
- change() //3 设置移入移出事件,显示与隐藏箭头
- wrap.onmouseover = function () {
- perfectAnimate(arrow, {'opacity': 1})
- }
- wrap.onmouseout = function () {
- perfectAnimate(arrow, {'opacity': 0})
- }
- /**
- *
- */
- function clearChangeConfig2() {
- if (cFlag) { //7.93 因为最开始点击箭头时,没有进行li的点击切换,不需要进行联动,只有点击过li后,再点击箭头才执行,可以
- // 使用cFlag作为判断条件
- cFlag = false //7.91 这里被调用是需要执行changeConfig1(this.index)里面的if判断,所以首先设置cFlag为false
- for (var i = 0; i < lis.length; i++) {
- //7.4 因为点击li后图片进行切换后,config中的元素又回到初始位置,与设置给li的并不相同,这时就需要
- // 将点击li时最后执行的changeConfig2(this.index),再退回到changeConfig1(this.index),要做到上一
- // 步,就需要找到当前点击的li的索引,因为当前点击的li肯定是设置有属性zIndex=4,并且其index属性保存了
- // 其索引值,所以通过这就可以找到需要的索引了。
- if (lis[i].style.zIndex == 4) {
- changeConfig1(lis[i].index)//7.5 找到索引后直接将config中元素的位置退回到changeConfig1(this.index)
- }
- }
- }
- }
- function pushCount() {
- if (count <= config.length && count > 0) {
- count--
- } else {
- count = 4
- }
- }
- function unshiftCount() {
- if (count < config.length && count >= 0) {
- count++
- } else {
- count = 0
- }
- }
- //4 添加右箭头点击事件
- arrRight.onclick = function () {
- if (flag) {//4.4 如果flag为true,即4.3假设成立,便执行下面的代码
- flag = false//4.5 给flag设置为false,使假设不成立,这时候只要没有改变flag值,点击事件源将不在执行这里的代码,不过此次下面代码依旧会执行
- clearChangeConfig2()//7.3 这里调用是为了点击li后,实现箭头的联动,具体看7.4
- config.push(config.shift())//4.1 点击后将第一个样式剪切到最后一个
- change()//4.2 通过调用函数,将新生成的config元素一一对应设置给li标签
//7.0 点击箭头后,实现与li点击联动,每次点击右箭头count值都会自减一次,count初始值为2.小于0后直接赋值为4
- //count的值对应的是每次进行切换后,zIndex值为4的元素在config中的索引值,并以此为初始值(取代6.5设置的2)——界面最前端的配置属性,使得点击li时正常切换
- pushCount() } } //5 添加左箭头点击事件
- arrLeft.onclick = function () {
- if (flag) {
- flag = false
- clearChangeConfig2()
- config.unshift(config.pop())//5.1 点击后将最后一个样式剪切到第一个
- change() //5.2 通过调用函数,将新生成的config元素一一对应设置给li标签
- unshiftCount()//7.1 将箭头点击与li点击联动,每次点击左箭头count值都会自增一次,count初始值为2.大于4后直接赋值为0
- }
- }
- /**
- * 6.3 根据当前点击的li的索引值,给li设置config内元素中的属性
- * @param i 当前点击li的索引值
- */
- function changeConfig1(i) {
- //6.5 未设置联动时,count位置应该是数字2,即最开始时zIndex值为4的config元素对应的索引,改变的中心思想为:zIndex中值为4的config元素(界面最前端的配置属性)
- // 总是设置给当前的点击的li,保持二者索引一致(count先不管)
- //6.6 然后进行判断,如果当前li的索引值小于等于2
- //7.2 这时将count作为条件依据,等同于以zIndex值为4的元素的索引为依据
- if (i <= count) {
- for (var i = i; i < count; i++) {
- config.push(config.shift())//6.7 那么根据其索引值进行0位config元素的剪切,直到zIndex值为4的config元素对应的索引与当前点击的li的索引一致
- if (cFlag == false) {//7.8 又因为点击li时,config元素与li进行对应设置后,又会回到初始位置,不会影响到count的变化
- //所以点击li时调用这个函数不能执行这个if判断,这里再次使用假设成立法,假设cFlag为false时执行if判断成立
- pushCount()//7.6 因为将config中元素的位置改为正常的后,zIndex=4的元素的索引又会发生变化,所以这时count也要跟着变化
- i--//7.7 这里的count为--,所以i值也要--才能保证count自减的次数与循环执行次数一致(即与config元素剪切的次数一致,即保证count的值总是配置单中zIndex=4的元素的索引)
- }
- }
- } else {
- for (var i = i; i > count; i--) {
- config.unshift(config.pop())//6.8 如果大于2,那么根据其索引值进行索引为4的config元素的剪切,直到zIndex值为4的config元素对应的索引与当前点击的li的索引一致
- if (cFlag == false) {
- unshiftCount()
- i++
- }
- }
- }
- }
- function changeConfig2(i) {
- if (i <= count) {
- for (var i = i; i < count; i++) {
- config.unshift(config.pop())
- if (cFlag == false) {
- pushCount()
- }
- }
- } else {
- for (var i = i; i > count; i--) {
- config.push(config.shift())
- if (cFlag == false) {
- unshiftCount()
- }
- }
- }
- }
- //6 遍历lis,给li设置点击事件
- for (var i = 0; i < lis.length; i++) {
- lis[i].index = i//6.4 以lis[i]的自定义属性index保存其索引值
- lis[i].onclick = function () {//6.1 添加事件
- cFlag = true //7.9 点击li时执行changeConfig1(this.index)之前将cFlag赋值true,即不执行它里面的if判断
- changeConfig1(this.index)//6.2 点击li后将zIndex值为4的config元素添加给当前点击的li,其他元素依次挪动。
- change()//6.9通过调用函数,将修改后的config内的元素属性一一对应设置给li
- changeConfig2(this.index)//6.91 在第6.2步中,zIndex值为4config元素进行过剪切可能已经不在索引为2的位置了,这时后我们再进行与6.2步中相反的操作
- // 将config中的元素位置回归到初始状态,但是并不设置给li.
- }
- }
}())- </script>
最后本着负责的态度,还是认真对着上面的文字检查了20分钟,确保在自己水平内将问题讲清楚——可是、好像还是不够太具体化...
看来只能等以后的理解更加透彻后,再对本文进行修改了。
——BY:骑士与魔王(我微博也是这个名字哈,里面还有自己之前玩微博时写的图文小说,《骑士与魔王》,可惜太监啦,哈哈哈哈)
Javascript学习记录——原生JS实现旋转木马特效的更多相关文章
- JavaScript学习记录三
title: JavaScript学习记录三 toc: true date: 2018-09-14 23:51:22 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- JavaScript学习记录二
title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- JavaScript学习记录四
title: JavaScript学习记录四 toc: true date: 2018-09-16 20:31:22 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- JavaScript学习记录一
title: JavaScript学习记录一 toc: true date: 2018-09-11 18:26:52 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- 原生js实现架子鼓特效
这是代码完成的效果,按下abcd会出现对应的架子鼓音乐的效果. 简单的介绍下代码思路,html和css部分就不多说了. 重要的是js部分. 大致是这样的, 首先获取到所有的按钮为一个数组,然后遍历整个 ...
- 原生JS实现旋转木马轮播图特效
大概是这个样子: 首先来简单布局一下(emm...随便弄一下吧,反正主要是用js来整的) <!DOCTYPE html> <html lang="en"> ...
- 诶西,JavaScript学习记录。。。。。。
由于大学课程缘故,老师巨爱叫人问问题,还记分呢,随便记录一下Js的学习情况,以后复习什么的也比较方便吧...... 开始咯,就按照C语言学习那样的方法来吧! ===================== ...
- 原生JS实现"旋转木马"效果的图片轮播插件
一.写在最前面 最近都忙一些杂七杂八的事情,复习软考.研读经典...好像都好久没写过博客了... 我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的, ...
- JavaScript学习记录总结(四)——js函数的特殊性
<script type="text/javascript"> //当局部变量与全局变量 重名的时候 var v="全局变量";//定义全局变 ...
随机推荐
- Swift 之模糊效果(毛玻璃效果,虚化效果)的实现
前言: 之前项目中有用到过Objective-C的的模糊效果,感觉很是不错,而且iOS8之后官方SDK也直接提供了可以实现毛玻璃效果的三个类:UIBlurEffect.UIVibrancyEffect ...
- IOS UIAppLocation 单例模式
UIApplocation * app=[UIApplocation shareapplocation]; UIAppLocation 只能被初始化一次. 一个程序中只能被创建一次,称为单例模式. 单 ...
- 安装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 ...
- 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 ...
- Python 爬虫2——环境配置
关于环境配置的操作,其实非常简单,假如不使用第三方的框架的话,只需要安装Python即可完成后续的操作. 一.Python的安装和配置: windows系统的安装配置过程如下,假如是Mac系统,可参考 ...
- AmazeUI 框架知识点-组件
1.Badge 默认:添加 .am-badge class 到 <div> 或者 <span> 元素. 圆角:在默认样式的基础上添加 .am-radius class. 椭圆: ...
- [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 ...
- 关于iOS后台问题( 一 )(ios后台刷新,后台定位,后台下载,真后台)
关于iOS的后台,以下引用一些文段进行一下脑补,请同学们大致看一下,有个基础,原文出处 -------------------------------------------------------- ...
- 定时任务crontab 例子
查看定时任务格式 [root@centos ~]# vim /etc/crontab 1 SHELL=/bin/bash 2 PATH=/sbin:/bin:/usr/sbin:/usr/bin 3 ...
- 工作中那些提高你效率的神器(第一篇)_Everything
引言 无论是工作还是科研,我们都希望工作既快又好,然而大多数时候却迷失在繁杂的重复劳动中,久久无法摆脱繁杂的事情. 你是不是曾有这样一种想法:如果我有哆啦A梦的口袋,只要拿出神奇道具就可解当下棘手的问 ...