zoukankan      html  css  js  c++  java
  • javascript 45种缓动效果BY司徒正美

    javascript 45种缓动效果

    参数类型说明
    el element 必需,为页面元素
    begin number 必需,开始的位置
    change number 必需,要移动的距离
    duration number 可选,缓动效果持续时间,默认是500ms。建议取300~1000ms。
    field string 必需,要发生变化的样式属性。请在top,left,bottom,right,width与height中选择。
    ftp number 可选,每秒进行多少帧动画,默认50帧,保证流畅播放。一些参考资料,日本动画1秒36帧,中国卡通24帧,赛车游戏60帧。
    ease function 必需,缓动公式,参数为0~1之间的数。可参考我下面给出的45条公式。
    onStart function 可选,在开始时执行。
    onEnd function 可选,在结束时执行。

    效果图:

    prototype流派的缓动公式,只需一个参数(增至45种)

      
    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=8">
            <title>JavaScript 45种缓动效果</title>
            <style type="text/css">
                .taxiway {
                     800px;
                    height: 100px;
                    background: #E8E8FF;
                }
                
                .move {
                     100px;
                    height: 100px;
                    background: #a9ea00;
                }
                
                #panel {
                    float: left;
                     810px
                }
                
                #panel div {
                    float: left;
                     88px;
                    border: 1px solid #333;
                    height: 20px;
                    font-size: 11px;
                }
                
                div.transition {
                    margin-top: 30px;
                     200px;
                    height: 200px;
                    position: relative;
                    margin-bottom: 10px;
                }
                
                div.transition div {
                    position: absolute;
                    height: 1px;
                     1px;
                    background: #000;
                }
                
                div.transition span {
                    display: block;
                    position: absolute;
                    border-bottom: 1px solid #dadada;
                    font-size: 10px;
                    color: #888;
                     200px;
                    left: 0px;
                }
                
                div.transition div#indicator {
                    position: absolute;
                    background-color: #a9ea00;
                    height: 200px;
                    top: 0px;
                    left: 0px;
                }
                
                div.transition div#marker {
                    background-color: #f00;
                    height: 6px;
                     6px;
                    border-radius: 3px;
                    -webkit-border-radius: 3px;
                    -moz-border-radius: 3px;
                    left: 0px;
                    margin-bottom: -3px;
                    margin-left: -3px;
                }
                
                div.transition div#label {
                    background: transparent;
                    color: #ABD474;
                    font-size: 20px;
                    height: 20px;
                     200px;
                    text-align: center;
                    top: 80px;
                    left: 0px;
                    z-index: -1;
                }
            </style>
            <script type="text/javascript">
                var getCoords = function(el) {
                    var box = el.getBoundingClientRect(),
                        doc = el.ownerDocument,
                        body = doc.body,
                        html = doc.documentElement,
                        clientTop = html.clientTop || body.clientTop || 0,
                        clientLeft = html.clientLeft || body.clientLeft || 0,
                        top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop) - clientTop,
                        left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft
                    return {
                        'top': top,
                        'left': left
                    };
                };
                var getStyle = function(el, style) {
                    if(!+"v1") {
                        style = style.replace(/-(w)/g, function(all, letter) {
                            return letter.toUpperCase();
                        });
                        var value = el.currentStyle[style];
                        (value == "auto") && (value = "0px");
                        return value;
                    } else {
                        return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
                    }
                }
                var tween = {
                    easeInQuad: function(pos) {
                        return Math.pow(pos, 2);
                    },
                    easeOutQuad: function(pos) {
                        return -(Math.pow((pos - 1), 2) - 1);
                    },
                    easeInOutQuad: function(pos) {
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(pos, 2);
                        return -0.5 * ((pos -= 2) * pos - 2);
                    },
                    easeInCubic: function(pos) {
                        return Math.pow(pos, 3);
                    },
                    easeOutCubic: function(pos) {
                        return(Math.pow((pos - 1), 3) + 1);
                    },
                    easeInOutCubic: function(pos) {
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(pos, 3);
                        return 0.5 * (Math.pow((pos - 2), 3) + 2);
                    },
                    easeInQuart: function(pos) {
                        return Math.pow(pos, 4);
                    },
                    easeOutQuart: function(pos) {
                        return -(Math.pow((pos - 1), 4) - 1)
                    },
                    easeInOutQuart: function(pos) {
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(pos, 4);
                        return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
                    },
                    easeInQuint: function(pos) {
                        return Math.pow(pos, 5);
                    },
                    easeOutQuint: function(pos) {
                        return(Math.pow((pos - 1), 5) + 1);
                    },
                    easeInOutQuint: function(pos) {
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(pos, 5);
                        return 0.5 * (Math.pow((pos - 2), 5) + 2);
                    },
                    easeInSine: function(pos) {
                        return -Math.cos(pos * (Math.PI / 2)) + 1;
                    },
                    easeOutSine: function(pos) {
                        return Math.sin(pos * (Math.PI / 2));
                    },
                    easeInOutSine: function(pos) {
                        return(-.5 * (Math.cos(Math.PI * pos) - 1));
                    },
                    easeInExpo: function(pos) {
                        return(pos == 0) ? 0 : Math.pow(2, 10 * (pos - 1));
                    },
                    easeOutExpo: function(pos) {
                        return(pos == 1) ? 1 : -Math.pow(2, -10 * pos) + 1;
                    },
                    easeInOutExpo: function(pos) {
                        if(pos == 0) return 0;
                        if(pos == 1) return 1;
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(2, 10 * (pos - 1));
                        return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
                    },
                    easeInCirc: function(pos) {
                        return -(Math.sqrt(1 - (pos * pos)) - 1);
                    },
                    easeOutCirc: function(pos) {
                        return Math.sqrt(1 - Math.pow((pos - 1), 2))
                    },
                    easeInOutCirc: function(pos) {
                        if((pos /= 0.5) < 1) return -0.5 * (Math.sqrt(1 - pos * pos) - 1);
                        return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);
                    },
                    easeOutBounce: function(pos) {
                        if((pos) < (1 / 2.75)) {
                            return(7.5625 * pos * pos);
                        } else if(pos < (2 / 2.75)) {
                            return(7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
                        } else if(pos < (2.5 / 2.75)) {
                            return(7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
                        } else {
                            return(7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
                        }
                    },
                    easeInBack: function(pos) {
                        var s = 1.70158;
                        return(pos) * pos * ((s + 1) * pos - s);
                    },
                    easeOutBack: function(pos) {
                        var s = 1.70158;
                        return(pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;
                    },
                    easeInOutBack: function(pos) {
                        var s = 1.70158;
                        if((pos /= 0.5) < 1) return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));
                        return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
                    },
                    elastic: function(pos) {
                        return -1 * Math.pow(4, -8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;
                    },
                    swingFromTo: function(pos) {
                        var s = 1.70158;
                        return((pos /= 0.5) < 1) ? 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) :
                            0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
                    },
                    swingFrom: function(pos) {
                        var s = 1.70158;
                        return pos * pos * ((s + 1) * pos - s);
                    },
                    swingTo: function(pos) {
                        var s = 1.70158;
                        return(pos -= 1) * pos * ((s + 1) * pos + s) + 1;
                    },
                    bounce: function(pos) {
                        if(pos < (1 / 2.75)) {
                            return(7.5625 * pos * pos);
                        } else if(pos < (2 / 2.75)) {
                            return(7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
                        } else if(pos < (2.5 / 2.75)) {
                            return(7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
                        } else {
                            return(7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
                        }
                    },
                    bouncePast: function(pos) {
                        if(pos < (1 / 2.75)) {
                            return(7.5625 * pos * pos);
                        } else if(pos < (2 / 2.75)) {
                            return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + .75);
                        } else if(pos < (2.5 / 2.75)) {
                            return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + .9375);
                        } else {
                            return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + .984375);
                        }
                    },
                    easeFromTo: function(pos) {
                        if((pos /= 0.5) < 1) return 0.5 * Math.pow(pos, 4);
                        return -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
                    },
                    easeFrom: function(pos) {
                        return Math.pow(pos, 4);
                    },
                    easeTo: function(pos) {
                        return Math.pow(pos, 0.25);
                    },
                    linear: function(pos) {
                        return pos
                    },
                    sinusoidal: function(pos) {
                        return(-Math.cos(pos * Math.PI) / 2) + 0.5;
                    },
                    reverse: function(pos) {
                        return 1 - pos;
                    },
                    mirror: function(pos, transition) {
                        transition = transition || tween.sinusoidal;
                        if(pos < 0.5)
                            return transition(pos * 2);
                        else
                            return transition(1 - (pos - 0.5) * 2);
                    },
                    flicker: function(pos) {
                        var pos = pos + (Math.random() - 0.5) / 5;
                        return tween.sinusoidal(pos < 0 ? 0 : pos > 1 ? 1 : pos);
                    },
                    wobble: function(pos) {
                        return(-Math.cos(pos * Math.PI * (9 * pos)) / 2) + 0.5;
                    },
                    pulse: function(pos, pulses) {
                        return(-Math.cos((pos * ((pulses || 5) - .5) * 2) * Math.PI) / 2) + .5;
                    },
                    blink: function(pos, blinks) {
                        return Math.round(pos * (blinks || 5)) % 2;
                    },
                    spring: function(pos) {
                        return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
                    },
                    none: function(pos) {
                        return 0
                    },
                    full: function(pos) {
                        return 1
                    }
                }
                var _ = function(id) {
                    return document.getElementById(id);
                }
                var 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,
                        onEnd = options.onEnd || function() {},
                        ease = options.ease, //要使用的缓动公式
                        end = begin + change, //结束位置
                        startTime = new Date().getTime(); //开始执行的时间
                    (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)
                    })()
                }
                if(typeof Array.prototype['max'] == 'undefined') {
                    Array.prototype.map = function(fn, thisObj) {
                        var scope = thisObj || window;
                        var a = [];
                        for(var i = 0, j = this.length; i < j; ++i) {
                            a.push(fn.call(scope, this[i], i, this));
                        }
                        return a;
                    };
                    Array.prototype.max = function() {
                        return Math.max.apply({}, this)
                    }
                    Array.prototype.min = function() {
                        return Math.min.apply({}, this)
                    }
                }
                var range = function(start, end) {
                    var _range = []
                    for(var i = start, l = end - start; i < l; i++) {
                        _range.push(i)
                    }
                    return _range
                }
                var draw = function(ease) {
                    var demo = _("transition");
                    demo.innerHTML = ""; //还原!
                    //***********绘制控制台********************
                    var values = range(0, 200).map(function(v) {
                            return tween[ease](v / 200) * 200;
                        }),
                        max = Math.max(200, values.max()),
                        min = Math.min(0, values.min());
                    if(min == max) {
                        min = 0;
                        max = 200;
                    }
                    var factor = 200 / (max - min),
                        grid = '<span style="bottom:' + Math.round((0 - min) * factor) + 'px">0</span>' +
                        '<span style="bottom:' + Math.round((200 - min) * factor) + 'px">1</span>',
                        graph = range(0, 200).map(function(v) {
                            return '<div style="left:' + v + 'px;bottom:' + Math.round((values[v] - min) * factor) + 'px;height:1px"></div>';
                        }).join('') + '<div id="indicator" style="display:none">' +
                        '</div><div id="marker" style="display:none"></div><div id="label"></div>';
                    demo.innerHTML = grid + graph;
                    var indicator = _("indicator"),
                        marker = _("marker"),
                        label = _("label"),
                        demoTransition = function(pos) {
                            var value = tween[ease](pos);
                            indicator.style.display = "block";
                            marker.style.display = "block";
                            marker.style.left = Math.round(pos * 200) + 'px';
                            marker.style.bottom = Math.round((value * 200 - min) * factor) + 'px';
                            label.innerHTML = Math.round(pos * 200) + 'px';
                            return value;
                        }
                    transition(indicator, {
                        field: "left",
                        begin: parseFloat(getCoords(demo).left),
                        change: 200,
                        ease: demoTransition
                    })
                }
                window.onload = function() {
                    var panelHTML = function() {
                        var builder = [];
                        var _temp = 'Back Circ Cubic Expo Quad Quart Quint Sine'.split(' ');
                        var ease = _temp.map(function(v) {
                            return 'easeIn' + v;
                        });
                        ease = ease.concat(_temp.map(function(v) {
                            return 'easeOut' + v;
                        }));
                        ease = ease.concat(_temp.map(function(v) {
                            return 'easeInOut' + v;
                        }));
                        ease = ease.concat('blink bounce bouncePast easeFrom easeFromTo easeOutBounce easeTo elastic'.split(' '));
                        ease = ease.concat('flicker full linear mirror none pulse reverse sinusoidal spring swingTo swingFrom swingFromTo wobble'.split(' '))
                        for(var i = 0, l = ease.length; i < l; i++) {
                            builder.push("<div onclick='draw(this.innerHTML)'>");
                            builder.push(ease[i]);
                            builder.push("</div>");
                        }
                        return builder.join('');
                    }
                    var panel = document.createElement("div");
                    panel.id = "panel"
                    panel.innerHTML = panelHTML();
                    _("transition").parentNode.insertBefore(panel, _("transition").nextSibling);
                }
            </script>
        </head>
    
        <body>
            <div class="taxiway">
                <div class="move" onclick="transition(this,{field:'left',begin:parseFloat(getCoords(this).left),change:700,ease:tween.bouncePast})"></div>
            </div>
            <div class="taxiway">
                <div class="move" onclick="transition(this,{field:'width',begin:parseFloat(getStyle(this,'width')),change:300,ease:tween.spring})"></div>
            </div>
            <span class="clear"></span>
            <h2>请点击下表的格子</h2>
            <div id="transition" class="transition">
            </div>
        </body>
    
    </html>
     
  • 相关阅读:
    子级必须浮动,父级如何自动适应高度
    如何应用JS来改变CSS样式
    php对多维数组按某值排序的例子
    php socket编程
    HLSL 高级着色语言基础
    谈谈.NET提供的各种记时器
    获取中文字符串的Unicode值的方法!
    Tab键和KeyDown,KeyUp事件
    公有字段和属性的选择!
    C#中汉字的繁体和简体的相互转换的两个方法!
  • 原文地址:https://www.cnblogs.com/wangyihong/p/8043156.html
Copyright © 2011-2022 走看看