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

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);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwypsd.html