原生JS改变透明度实现轮播效果


Posted in Javascript onMarch 24, 2017

在我看来要想实现轮播主要是要知道当前位于的页面和即将位于的页面。这个案例是通过改变图片的透明度来实现轮播的效果。

我把涉及的知识点分为两个方面,分别是HTML+css和JS。

第一部分(html+css)

包含的知识有:positon定位。

最外层是一个div,它包含了所有的元素。这个轮播一共有三张图片,这三张图片包含在一个无序列表中。最外层的div还有两个用来切换上一张图片和下一张图 片的子元素。这两个子元素也是div,切换上一张图片的div的id属性为pre,切换下一张图片的div的id属性为next。最外层div的 position值为relative。包含图片的无序列表的position为relative。无序列表中的li元素的positon属性值为 absolute,这会让li元素位于文档流之外,所以如果不显示的设置ul的高度,ul高度为零。但是我们不能用css去显示设置ul的高度。因为需要 让这个轮播的高度等于图片的高度,并且要保证在不同分辨率的计算机上图片的高宽比保持不变。在不同分辨率的计算机上图片显示出的高度和宽度是不一样的。所 以我是通过js去设置ul的高度。因为ul的position的属性值为relative,所以ul的高度会撑开外层div的高度。由于这个案例是通过改 变图片透明度实现轮播,所以所有的图片位于同一个位置,在默认情况下最后一张图片会在最上面,第一个图片是在最下面,而轮播第一张显示的图片图片应该是第 一张,然后是第二张,最后才是第三张,所以要显示的对每个li设置z—index属性。并且z-index属性值依次递减。我是用js去设置每一个li的 z-index属性值,但其实并没有必要这样做,直接用css属性就可以了,只不过要写三个选择器。

html如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>通过改变透明度实现轮播</title>
 <link rel="stylesheet" type="text/css" href="index.css" rel="external nofollow" >
</head>
<body>
 <div class='warp' id='warp'>
 <ul class='list' id='list'>
  <li><img src='img/4274ad202b27b671e622388989399d54.jpg' style='opacity: 1'></li>
  <li><img src='img/299733ddbe89d6b317cc0e84c43999d4.jpg' style='opacity: 1'></li>
  <li><img src='img/9b7ec36280e638929aa10ce0955df3d3.jpg' style='opacity: 1'></li>
 </ul>
 <div class='pre' id='pre'>《</div>
 <div class='next' id='next'>》</div>
 </div>
 <script type="text/javascript" src='index.js'></script>
</body>
</html>

css代码如下

*{
 padding: 0;
 margin: 0;
}
.warp{
 position: relative;
 width: 100%;
}
.list{
 position: relative;
 width: 100%;
}
.list li{
 position: absolute;
 top:0;
 left: 0;
 width: 100%;
 list-style: none;
 opacity: 1;
}
li img{
 width: 100%;
}
.pre,.next{
 position: absolute;
 top: 50%;
 bottom: 0;
 width: 64px;
 height: 64px;
 z-index: 10;
 margin-top: -32px;
 text-align: center;
 line-height: 64px;
 color: #fff;
 font-weight: bold;
 font-size: 30px;
 cursor: pointer;
 background-color: transparent;
}
.pre{
 left: 20px;
 right: auto;
}
.next{
 right:20px;
 left: auto;
}
.pre:hover,.next:hover{
 background-color: rgba(0,0,0,0.7);
}

第二部分(js)涉及的知识有:事件,函数节流,设置定时器,清除定时器
事件由于用的是原生js去实现功能,所以需要考虑浏览器兼容问题。

事件流

有 两种类型的时间流,分别是事件冒泡流和事件捕获流,这差不多是完全相反的事件流概念,事件冒泡流叫做事件冒泡,这是IE提出的。以一个click事件为 例,在事件冒泡中事件首先发生在最具体的那个元素上,也就是我们单击的那个元素,然后沿着dom树向上传播,在传播的过程中,每一级节点都会发生 click事件,直到传播的document对象。事件捕获流叫做事件捕获,这是由Netscape Communicator提出的。同样以一个 click事件为例,在事件捕获中事件首先发生在最不具体的那个节点上(document对象首先接收到事件),然后沿着dom树向下传播,最具体的节点 最后接收到事件,也就是说,实际上被点击的那个元素最后接收click事件。“DOM2级事件”规定事件流包括三个阶段,分别为事件捕获阶段,处于目标阶 段和事件冒泡阶段。在主流浏览器中除了IE不支持DOM事件流,其他浏览器都支持DOM事件流。所以IE之支持事件冒泡。但是在将来IE应该会支持DOM 事件流。那时候在绑定事件的时候就不用考虑浏览器兼容问题了。目前为了最大程度的兼容各种浏览器,我将事件处理程序添加到事件流的冒泡阶段。

事件处理程序

》DOM0级事件处理程序

DOM0 级使用为元素的属性赋值的方式绑定事件,将事件处理程序属性的值设置为一个函数即可。程序中的this指当前元素。删除通过DOM0级方法绑定的事件方法 是:将事件处理程序的属性设置为null。如果一个元素绑定了事件,在把这个元素移除文档之前,最好手动的的解除这个元素绑定的事件。这样可以防止元素已 经被移除了但是该元素的事件处理程序的引用还保持在内存中。所以的现代浏览器都支持DOM0级事件处理程序。但是用DOM0级绑定事件时,每个元素同一个 事件只能添加一个事件处理程序。

》DOM2级事件处理程序

在“DOM2级事件”中指定事件处理程序的方法为:addEventListener(),第一个参是一个事件名,第二个参数为一个事件处理程序(即一个函 数,可以是匿名函数),第三个参数是一个布尔值。这个布尔值表示在哪一个阶段处理事件,当为false时表示在冒泡阶段处理,当为true时表示在捕获阶 段处理。为了兼容性我将这个值设置为false。解除用“DOM2级事件”绑定的时间处理程序,需要使用removeEventListener(),匿 名的事件处理程序不能被解除。使用“DOM2级事件”绑定事件时,每个元素同一个事件可以添加多个事件处理程序。用“DOM2级事件”绑架的事件处理程 序,this是指当前元素。

》IE事件处理程序

在IE中指定事件处理程序的方法是 attachEvent(),第一个参数是事件处理程序名(即“on”+事件名),第二个参数是时间处理程序(一个函数,可以是匿名函数)。由于IE只支 持事件冒泡所以事件在冒泡阶段处理。使用detachEvent()可以移除用attachEvent()添加的时间处理程序,但是匿名函数不能被移除。 使用attachEvent()绑定事件this指window。。使用attachEvent绑定事件时,每个元素同一个事件可以添加多个事件处理程序。

注:匿名函数不能被移除的原因是:在js中函数是一个对象,这个对象被保存在堆里,函数名是一个指针,指向堆里的对象。对于一个匿名函数而言没有指针指向它,所以就访问不到。

事件对象

在兼容DOM的浏览器中,事件对象是作为一个参数传递到事件处理程序中。(即在兼容DOM的浏览器,不论是通过DOM0级或DOM2级绑定事件,都会将事件 对象作为参数传递到事件处理程序中),当时IE浏览器中,如果用DOM0级指定时间处理程序,事件对象是保存在window的event属性中,如果用 attachEvent()指定时间处理程序,事件对象是作为一个参数传递到事件处理程序中。在兼容DOM的浏览器的事件对象中的值和IE的事件对象中的 值存在差异。但它们都有一个共同的值——type(即:被触发的时间的类型)。在兼容DOM的浏览器中,事件对象的target属性表示事件的目标,以一 个click事件为例,target属性指最具体的那个元素。在IE浏览器中,事件对象的srcElement属性表示事件目标

在这个案例中,我为最外层的div(它的id为warp)添加了一个click的事件处理程序。通过判断事件目标的id值确定触发事件最具体的那个节点。如果事件目 标的id值为pre则切换到上一个图片,如果事件目标的id值为next则切换到下一张图片。这儿用的是事件代理,事件代理可以减少使用的内存。

函数节流在这个案例中使用函数节流是为了减少当连续触发resize事件时浏览器的计算量,因为如果浏览器的计算量太大,浏览器会变慢,甚至崩溃。函数节流的主要思 路是当事件被触发时,在事件处理程序中,并不是立即做计算,而是使用setTimeout或者setInterval在指定的时间后进行计算。

设置定时器和清除定时器由于要完全讲清楚定时器还涉及浏览器线程和js的单线程执行等问题现在不做讲解。主要是我也还没有完全的搞明白。在这里提一下浏览器是多线程的,开启定时器 是在浏览器的定时器线程,js执行程序是在浏览器的另一个线程。浏览器除了这两个线程还没有其他的线程。等我也明白了浏览器线程之间的联系以后我会再写一 篇文章。

在这个实例中改变图片的透明度是通过设置定时器逐渐变大或者逐渐变小。在增加下一张图片的不透明度之前,要先将当前图片的不透名都减小到0。

打开页面自动播放,也是用定时器实现的,如果要停止播放,就清除定时器

js代码如下 

// 当页面加载完成后将所以需要执行的函数添加到window的load事件上。这儿用的是dom0级事件的绑定,所以不能为window的load事件添加 多个事件处理程序,所以使用的方法是:先判断window.onload有没有绑定函数,如果绑定了,就将新的函数追加到尾部,如果没有绑定,就直接添加 给它。用attachEvent()或者addEventListener()可以为同一个元素的同一个事件绑定多个事件处理程序,可以不用下面这个方法。

function addLoadEvent(func){
 var oldLoad = window.onload;
 if(typeof oldLoad != 'function'){
 window.onload = func();
 }else{
 window.onload = function(){
  oldLoad();
  func();
 }
 }
}



//设置class为list的高度,因为图片的position为absolute所以.list元素的高度为零
//如果一个元素的父元素高度为0,那么设置这个元素的margin: auto 0; 不起作用
function setListHeight(){
 var list = document.getElementById('list');
 var imgItem = list.getElementsByTagName('img')[0];
 var height = imgItem.offsetHeight;
 var list = document.getElementById('list');
 list.style.height = height + 'px';
}

//设置li的层级,可以使用css设置
function setLiIndex(){
 var list = document.getElementById('list');
 var li = list.getElementsByTagName('li');
 var liLen = li.length;
 for(var i = 0;i<liLen;i++){
 li[i].style.zIndex = liLen-i;
 }
}
var index = 1;//index表示当前显示的页面,index是一个全局变量
var timer;// 定时器标识符,如果要清除定时器需要使用它

//事件的跨浏览器绑定的对象
var untilEvent = {
 addEvent:function(element,type,hander){
 if(element.addEventListener){
  element.addEventListener(type,hander,false);
 }else if(element.attachEvent){
  element.attachEvent('on'+type,hander);
 }else{
  element['on'+type] = hander;
 }
 },
 getEvent:function(event){
 return event?event:window.event;
 },
 getTarget:function(event){
 return event.target||event.srcElement;
 }

};
function btnClick(){
 var warp = document.getElementById('warp');
 untilEvent.addEvent(warp,'click',function(event){
 var event = untilEvent.getEvent(event);
 var target = untilEvent.getTarget(event);
 switch(target.id){
  case 'pre': if(index == 1){//如果当前显示的图片已经是第一张图片,当点击切换到"上一张"按钮,则将即将显示的图片设置为最后一张图片
   index =3;
  }else{
   --index;
  }
  anmitate();
  break;
  case 'next':if(index == 3){//如果当前显示的图片已经是最后图片,当点击切换到"下一张"按钮,则将即将显示的图片设置为第一张图片
  index = 1;
  }else{
   ++index;
  }
  anmitate();
  break;
 }
 });
}
//减小图片透明度
function decline(cur,inverTime,inverOpacity){
 var opacityed = parseFloat(cur.style.opacity);
 if(opacityed > 0){
 cur.style.opacity = opacityed-inverOpacity;
 setTimeout(function(){
  decline(cur,inverTime,inverOpacity);
 },inverTime);
 }
}
//切换图片的函数
function anmitate(){
 var list = document.getElementById('list');
 var imgs = list.getElementsByTagName('img');
 var imgsLen = imgs.length;
 var whole = 300;//切换一张图片用的时间
 var inverTime = 5;//时间间隔
 var inverOpacity = 1/(whole/inverTime);
 for(var i = 0;i<imgsLen;i++){
 decline(imgs[i],inverTime,inverOpacity);
 }
 var go = function(){
 var opacityed = parseFloat(imgs[index - 1].style.opacity);
 if(opacityed < 1){
  imgs[index-1].style.opacity = opacityed + inverOpacity;
  setTimeout(go,inverTime);
 }
 };
 go();
}
//打开页面自动切换函数
function play() {
 timer = setTimeout(function () {
 if(index == 3){
  index = 1;
 }else{
  ++index;
 }
 anmitate();
  play();
  //
 }, 3000);
}
//停止切换函数,当鼠标移动到轮播上后取消自动切换,当鼠标从轮播上移开,又开始自动切换
function stop() {
 clearTimeout(timer);
}

//给最外层div添加鼠标移除和鼠标移入地事件处理程序
function getWarp(){
 var warp = document.getElementById('warp');
 untilEvent.addEvent(warp,"mouseout",play);
 untilEvent.addEvent(warp,"mouseover",stop);
}
//函数节流,当改变窗口大小时,图片的大小会变化,所以为了让控制按钮位于轮播垂直方向的中间,li的高度该随图片的大小做变化
function scrollEvent(){
 untilEvent.addEvent(window,"resize",function(){
 throttle(setListHeight);
 });
}
function throttle(method,context){
 clearTimeout(method.Tid);
 method.Tid = setTimeout(method,70);
}
addLoadEvent(scrollEvent);
addLoadEvent(setListHeight);
addLoadEvent(setLiIndex);
addLoadEvent(btnClick);
addLoadEvent(play);
addLoadEvent(getWarp);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript Cookie 直接浏览网站分网址
Dec 08 Javascript
jQuery生成asp.net服务器控件的代码
Feb 04 Javascript
JavaScript之引用类型介绍
Aug 10 Javascript
javascript使用中为什么10..toString()正常而10.toString()出错呢
Jan 11 Javascript
js 验证身份证信息有效性
Mar 28 Javascript
js类定义函数时用prototype与不用的区别示例介绍
Jun 10 Javascript
JavaScript中length属性的使用方法
Jun 05 Javascript
javascript中对象的定义、使用以及对象和原型链操作小结
Dec 14 Javascript
Bootstrap select下拉联动(jQuery cxselect)
Jan 04 Javascript
vue组件之间的数据传递方法详解
Apr 19 Javascript
使用element-ui +Vue 解决 table 里包含表单验证的问题
Jul 17 Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
Jul 28 Javascript
深入理解vue路由的使用
Mar 24 #Javascript
原生JS实现导航下拉菜单效果
Nov 25 #Javascript
jQuery插件FusionCharts实现的MSBar2D图效果示例【附demo源码】
Mar 24 #jQuery
基于HTML5+JS实现本地图片裁剪并上传功能
Mar 24 #Javascript
详解Vue-基本标签和自定义控件
Mar 24 #Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 #Javascript
jQuery编写textarea输入字数限制代码
Mar 23 #jQuery
You might like
《DOTA3》开发工作已经开始 《DOTA3》将代替《DOTA2》
2021/03/06 DOTA
PHP读写文件的方法(生成HTML)
2006/11/27 PHP
PHP开发框架总结收藏
2008/04/24 PHP
浏览器无法运行JAVA脚本的解决方法
2008/01/09 Javascript
Javascript中的window.event.keyCode使用介绍
2011/04/26 Javascript
学习js在线html(富文本,所见即所得)编辑器
2012/12/18 Javascript
jQuery之日期选择器的深入解析
2013/06/19 Javascript
延时加载JavaScript代码提高速度
2015/12/27 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
2016/05/20 Javascript
js添加千分位的实现代码(超简单)
2016/08/01 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
2016/10/10 Javascript
详解JavaScript中的属性和特性
2016/12/08 Javascript
bootstrap datetimepicker实现秒钟选择下拉框
2017/01/05 Javascript
three.js快速入门【推荐】
2017/01/21 Javascript
AngularJS实用基础知识_入门必备篇(推荐)
2017/07/10 Javascript
基于Vue实现电商SKU组合算法问题
2019/05/29 Javascript
JavaScript进阶(三)闭包原理与用法详解
2020/05/09 Javascript
VUE异步更新DOM - 用$nextTick解决DOM视图的问题
2020/11/06 Javascript
一文秒懂nodejs中的异步编程
2021/01/28 NodeJs
Python中用Descriptor实现类级属性(Property)详解
2014/09/18 Python
Python外星人入侵游戏编程完整版
2020/03/30 Python
浅谈Python实现贪心算法与活动安排问题
2017/12/19 Python
python交换两个变量的值方法
2019/01/12 Python
django-allauth入门学习和使用详解
2019/07/03 Python
wxPython电子表格功能wx.grid实例教程
2019/11/19 Python
Python进程池Pool应用实例分析
2019/11/27 Python
python pillow库的基础使用教程
2021/01/13 Python
Under Armour西班牙官网:美国知名的高端功能性运动品牌
2018/12/12 全球购物
一些Unix笔试题和面试题
2013/01/22 面试题
介绍一下Prototype的$()函数,$F()函数,$A()函数都是什么作用?
2014/03/05 面试题
销售人员中英文自荐信
2013/09/22 职场文书
大学旷课检讨书
2014/01/28 职场文书
中学教师暑期培训方案
2014/08/27 职场文书
党干部专题民主生活会对照检查材料思想汇报
2014/10/06 职场文书
小学推普周活动总结
2015/05/07 职场文书
员工工作失职检讨书范文!
2019/07/03 职场文书