朋友让帮忙找个原生JS写的带缓动效果的图片幻灯,类似Tmall首页的效果,找了一圈后发现网上JS写的图片幻灯很多,相关的jQuery插件也很多,但用原生JS写的带缓动效果的却不多。没办法只好自己动手,现在把代码分享给大家,希望对大家有用。
代码中的缓动公式用了司徒正美博客中整理的代码:http://www.cnblogs.com/rubylouvre/archive/2009/09/17/1567607.html
缓动公式的推导主要利用了物理中的加速度知识,推荐过程可以看看这篇文章:http://floatyears.info/javascript-animation-easing
HTML部分:
- <div id="J-Slide">
- <ul class="JSlide-list">
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_01.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_02.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_03.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_04.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_05.jpg" alt=""/></li>
- </ul>
- <ul class="JSlide-num">
- <li class="current">1</li>
- <li>2</li>
- <li>3</li>
- <li>4</li>
- <li>5</li>
- </ul>
- <div class="JSlide-mask"></div>
- </div>
这部分比较简单,跟Tmall首页效果一样,几张图片,左下角是图片索引,并有一个半透明的遮罩层。
CSS部分:
- body,ul,li{
- margin:0;
- padding:0;
- }
- ul{
- list-style:none;
- }
- #J-Slide{
- width:600px;
- height:400px;
- position:relative;
- margin:50px auto;
- overflow:hidden;
- }
- #J-Slide .JSlide-list{
- position:absolute;
- width:3000px;
- left:0;
- top:0;
- }
- #J-Slide .JSlide-list li{
- float:left;
- }
- #J-Slide .JSlide-list li img{
- width:600px;
- height:400px;
- }
- #J-Slide .JSlide-num{
- position:absolute;
- left:0;
- bottom:0;
- height:30px;
- padding:5px;
- width:100%;
- z-index:10;
- }
- #J-Slide .JSlide-num li{
- width:30px;
- height:30px;
- margin-left:10px;
- float:left;
- font-size:16px;
- color:white;
- background:#716584;
- line-height:30px;
- text-align:center;
- cursor:pointer;
- border-radius:15px;
- }
- #J-Slide .JSlide-mask{
- position:absolute;
- left:0;
- background:black;
- bottom:0;
- width:100%;
- height:40px;
- opacity:0.3;
- filter:Alpha(opacity = 30);
- z-index:1;
- }
- #J-Slide .JSlide-num .current{
- background:#B91919;
- }
CSS部分比较简单,直接用absolute定位。
JavaScript库部分:
- (function(){
- /*
- *参数说明:
- *id 必须
- *picwidth 可选
- *speed 可选
- *
- *作者:artwl
- *出处:http://artwl.cnblogs.com
- */
- var JCP_Slide=function(id,picwidth,speed){
- if(!(this instanceof JCP_Slide))
- return new JCP_Slide(id,picwidth,speed);
- var obj=document.getElementById(id),
- childs=obj.getElementsByTagName("ul");
- this.author="artwl";
- this.jslideList=childs[0];
- this.jslideNums=childs[1].children;
- this.speed= speed || 5000;
- this.picwidth= picwidth || (obj.currentStyle ? parseFloat(obj.currentStyle.width) : parseFloat(document.defaultView.getComputedStyle(obj,null).width));
- this.currentIndex=0;
- this.distance=this.picwidth;
- this.currentLeftPos=0;
- this.runHandle=null;
- this.len=this.jslideNums.length;
- }
- JCP_Slide.prototype={
- bindMouse:function(){
- var self=this;
- for(var i=0;i<this.len;i++){
- this.jslideNums[i].onmouseover=(function(index){
- return function(){
- self.currentIndex=index;
- clearInterval(self.runHandle);
- var prev=-1;
- for(var k=0;k<self.len;k++){
- if(self.jslideNums[k].className === "current")
- prev = k;
- self.jslideNums[k].className = k === index ? "current" : "" ;
- }
- if(prev != index){
- self.distance=(prev - index)*self.picwidth;
- self.currentLeftPos = -prev * self.picwidth;
- self.transition(self.jslideList,{field:'left',begin:self.currentLeftPos,change:self.distance,ease:self.easeOutCirc})
- }
- }
- })(i);
- this.jslideNums[i].onmouseout=function(){
- self.autoRun();
- }
- }
- },
- autoRun:function(){
- var self=this;
- this.runHandle=setInterval(function(){
- self.distance=-self.picwidth;
- for(var k=0;k<self.len;k++){
- self.jslideNums[k].className = "" ;
- }
- self.currentIndex++;
- self.currentIndex%=5;
- self.jslideNums[self.currentIndex].className = "current";
- self.currentLeftPos = -(self.currentIndex-1) * self.picwidth;
- if(self.currentIndex == 0){
- self.distance = (self.len-1)*self.picwidth;
- self.currentLeftPos = -self.distance;
- }
- self.transition(self.jslideList,{field:'left',begin:self.currentLeftPos,change:self.distance,ease:self.easeOutCirc});
- },self.speed);
- },
- easeOutCirc:function(pos){
- return Math.sqrt(1 - Math.pow((pos-1), 2))
- },
- transition:function(el){
- el.style.position = "absolute";
- var options = arguments[1] || {},
- begin = options.begin,//开始位置
- change = options.change,//变化量
- duration = options.duration || 500,//缓动效果持续时间
- field = options.field,//必须指定,基本上对top,left,width,height这个属性进行设置
- ftp = options.ftp || 50,
- onStart = options.onStart || function(){},
- onEnd = options.onEnd || function(){},
- ease = options.ease,//要使用的缓动公式
- end = begin + change,//结束位置
- startTime = new Date().getTime();//开始执行的时间
- onStart();
- (function(){
- setTimeout(function(){
- var newTime = new Date().getTime(),//当前帧开始的时间
- timestamp = newTime - startTime,//逝去时间
- delta = ease(timestamp / duration);
- el.style[field] = Math.ceil(begin + delta * change) + "px";
- if(duration <= timestamp){
- el.style[field] = end + "px";
- onEnd();
- } else {
- setTimeout(arguments.callee,1000/ftp);
- }
- },1000/ftp);
- })();
- },
- play:function(){
- this.bindMouse();
- this.autoRun();
- }
- };
- window.JCP_Slide=JCP_Slide;
- })();
这个JS库是核心,入口有三个参数,***个是最外层的div的id(必须),第二个参数是图片宽度(可选),默认为最外层DIV宽度,第三个参数为自动切换的时间间隔(可选),默认为5秒。
bindMouse是绑定鼠标的悬浮和移出事件,autoRun是让图片正动切换,play方法调用了这两个方法。
easeOutCirc是一个先快后慢的缓动公式,transition是缓动函数,这两个方法的用法请参考司徒正美的博客:
调用示例:
- window.onload=function(){
- JCP_Slide("J-Slide").play();
- };
完整代码为:
- View Code
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8"/>
- <title> New Document </title>
- <style type="text/css">
- body,ul,li{
- margin:0;
- padding:0;
- }
- ul{
- list-style:none;
- }
- #J-Slide{
- width:600px;
- height:400px;
- position:relative;
- margin:50px auto;
- overflow:hidden;
- }
- #J-Slide .JSlide-list{
- position:absolute;
- width:3000px;
- left:0;
- top:0;
- }
- #J-Slide .JSlide-list li{
- float:left;
- }
- #J-Slide .JSlide-list li img{
- width:600px;
- height:400px;
- }
- #J-Slide .JSlide-num{
- position:absolute;
- left:0;
- bottom:0;
- height:30px;
- padding:5px;
- width:100%;
- z-index:10;
- }
- #J-Slide .JSlide-num li{
- width:30px;
- height:30px;
- margin-left:10px;
- float:left;
- font-size:16px;
- color:white;
- background:#716584;
- line-height:30px;
- text-align:center;
- cursor:pointer;
- border-radius:15px;
- }
- #J-Slide .JSlide-mask{
- position:absolute;
- left:0;
- background:black;
- bottom:0;
- width:100%;
- height:40px;
- opacity:0.3;
- filter:Alpha(opacity = 30);
- z-index:1;
- }
- #J-Slide .JSlide-num .current{
- background:#B91919;
- }
- </style>
- <script>
- (function(){
- /*
- *参数说明:
- *id 必须
- *picwidth 可选
- *speed 可选
- *
- *作者:artwl
- *出处:http://artwl.cnblogs.com
- */
- var JCP_Slide=function(id,picwidth,speed){
- if(!(this instanceof JCP_Slide))
- return new JCP_Slide(id,picwidth,speed);
- var obj=document.getElementById(id),
- childs=obj.getElementsByTagName("ul");
- this.author="artwl";
- this.jslideList=childs[0];
- this.jslideNums=childs[1].children;
- this.speed= speed || 5000;
- this.picwidth= picwidth || (obj.currentStyle ? parseFloat(obj.currentStyle.width) : parseFloat(document.defaultView.getComputedStyle(obj,null).width));
- this.currentIndex=0;
- thisthis.distance=this.picwidth;
- this.currentLeftPos=0;
- this.runHandle=null;
- thisthis.len=this.jslideNums.length;
- }
- JCP_Slide.prototype={
- bindMouse:function(){
- var self=this;
- for(var i=0;i<this.len;i++){
- this.jslideNums[i].onmouseover=(function(index){
- return function(){
- self.currentIndex=index;
- clearInterval(self.runHandle);
- var prev=-1;
- for(var k=0;k<self.len;k++){
- if(self.jslideNums[k].className === "current")
- prev = k;
- self.jslideNums[k].className = k === index ? "current" : "" ;
- }
- if(prev != index){
- self.distance=(prev - index)*self.picwidth;
- self.currentLeftPos = -prev * self.picwidth;
- self.transition(self.jslideList,{field:'left',begin:self.currentLeftPos,change:self.distance,ease:self.easeOutCirc})
- }
- }
- })(i);
- this.jslideNums[i].onmouseout=function(){
- self.autoRun();
- }
- }
- },
- autoRun:function(){
- var self=this;
- this.runHandle=setInterval(function(){
- self.distance=-self.picwidth;
- for(var k=0;k<self.len;k++){
- self.jslideNums[k].className = "" ;
- }
- self.currentIndex++;
- self.currentIndex%=5;
- self.jslideNums[self.currentIndex].className = "current";
- self.currentLeftPos = -(self.currentIndex-1) * self.picwidth;
- if(self.currentIndex == 0){
- self.distance = (self.len-1)*self.picwidth;
- self.currentLeftPos = -self.distance;
- }
- self.transition(self.jslideList,{field:'left',begin:self.currentLeftPos,change:self.distance,ease:self.easeOutCirc});
- },self.speed);
- },
- easeOutCirc:function(pos){
- return Math.sqrt(1 - Math.pow((pos-1), 2))
- },
- transition:function(el){
- el.style.position = "absolute";
- var options = arguments[1] || {},
- begin = options.begin,
- change = options.change,
- duration = options.duration || 500,
- field = options.field,
- ftp = options.ftp || 50,
- onStart = options.onStart || function(){},
- onEnd = options.onEnd || function(){},
- ease = options.ease,
- end = begin + change,
- startTime = new Date().getTime();
- onStart();
- (function(){
- setTimeout(function(){
- var newnewTime = new Date().getTime(),
- timestamp = newTime - startTime,
- delta = ease(timestamp / duration);
- el.style[field] = Math.ceil(begin + delta * change) + "px";
- if(duration <= timestamp){
- el.style[field] = end + "px";
- onEnd();
- } else {
- setTimeout(arguments.callee,1000/ftp);
- }
- },1000/ftp);
- })();
- },
- play:function(){
- this.bindMouse();
- this.autoRun();
- }
- };
- window.JCP_Slide=JCP_Slide;
- })();
- window.onload=function(){
- JCP_Slide("J-Slide").play();
- };
- </script>
- </head>
- <body>
- <div id="J-Slide">
- <ul class="JSlide-list">
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_01.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_02.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_03.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_04.jpg" alt=""/></li>
- <li><img src="http://images.cnblogs.com/cnblogs_com/artwl/357654/o_05.jpg" alt=""/></li>
- </ul>
- <ul class="JSlide-num">
- <li class="current">1</li>
- <li>2</li>
- <li>3</li>
- <li>4</li>
- <li>5</li>
- </ul>
- <div class="JSlide-mask"></div>
- </div>
- </body>
- </html>
运行效果:
原文链接:http://www.cnblogs.com/artwl/archive/2012/09/06/2673649.html