分享一个用原生JavaScript写的带缓动效果的图片幻灯

朋友让帮忙找个原生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是缓动函数,这两个方法的用法请参考 司徒正美 的博客:http://www.cnblogs.com/rubylouvre/archive/2009/09/17/1567607.html

调用示例:

window.onload=function(){
    JCP_Slide("J-Slide").play();
};

完整代码为:

<!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;
                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,
                    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;
        })();

        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

posted @ 2012-10-15 13:17  培哥  阅读(238)  评论(0编辑  收藏  举报