同时运动的另外一种解决方案,拿走,不谢

来源:6-2 完美运动框架

风_起

2016-04-21 14:09

    UtilJS.DOMUtil = function(){};

    /**
     * 获取元素当前的样式(即计算后的样式)
     * 
     * @param  {Element} element  目标元素
     * @param  {String} attrName 指定样式属性的名称
     * @return {String}          指定样式属性的值
     */
    UtilJS.DOMUtil.getSpecifiedStyleOnElement = function(element, attrName){
        if(getComputedStyle){
            return getComputedStyle(element, null)[attrName];//只能用[],却不能用getPropertyValue,为啥???
        }
        else{
            return element.currentStyle[attrName];
        }
    };
    UtilJS.AnimationUtil = function(){};
    /**
         * 封装几种常见CSS样式属性变化的运动(1个或几个CSS属性的同时缓冲运动,通过endFun参数可以变为链式缓冲运动)
         * 
         * @param  {Element} element     目标元素
         * @param  {String} attrName    样式名
         * @param  {Number} targetValue 运动结束的条件-目标值
         * @param  {Number} msec        运动定时器的间隔时间
         * @param  {Function} endFun      可选,定时器结束后触发该函数
         */
        UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed = function(element, attrName, targetValue, msec, endFun){
            //给元素绑定一个定时器数组对象(该元素每一个需要改变的样式对应一个定时器)
            if(!element.timers)
                element.timers = {};

            //给需要运动的元素添加定时器属性
            if(!element.timers[attrName]){
                element.timers[attrName] = null;
            }
            else
                clearInterval(element.timers[attrName]);

            //判断是否为“透明度运动”
            if(attrName == "opacity"){
                var isOpacityAttr = true;
                if(!element.alpha)
                    element.alpha = Math.round(parseFloat(UtilJS.DOMUtil.getSpecifiedStyleOnElement(element, attrName)) * 100);
            }

            //定时器函数
            element.timers[attrName] = setInterval(function(){
                //1.获取目标元素的指定的样式值
                if(isOpacityAttr)
                    var styleValue = Math.round(parseFloat(UtilJS.DOMUtil.getSpecifiedStyleOnElement(element, attrName)) * 100);
                else
                    var styleValue = parseInt(UtilJS.DOMUtil.getSpecifiedStyleOnElement(element, attrName));

                //2.计算缓冲运动的速度
                var speed = (targetValue - styleValue) / 8;
                speed = speed>0 ? Math.ceil(speed) : Math.floor(speed);

                //3.运动结束判断
                if(styleValue == targetValue){//3.1运动结束
                    clearInterval(element.timers[attrName]);
                    if(endFun && (typeof endFun == "function"))
                        endFun();
                }
                else{//3.2运动没有结束
                    if(isOpacityAttr){
                        element.alpha += speed;
                        element.style.filter = "alpha(opacity:" + element.alpha + ")";
                        element.style.opacity = element.alpha / 100;
                    }
                    else{
                        element.style[attrName] = styleValue + speed + "px";
                    }
                }
            }, msec);
        }
    }
  1. 老师的这个运动框架不能说完美,应该适合于解决几种常见CSS样式属性变化的情况;

  2. 上面的代码,包括缓冲运动、链式运动和同时运动;

写回答 关注

3回答

  • 风_起
    2016-04-21 16:32:47

    再补充一点:后面的element.alpha可以换成styleValue,并且isOpactiy也不需要了。(代码忘记更新了)

  • 风_起
    2016-04-21 14:44:21

    好吧,并没有bug,在实现同时和链式运动的时候只要注意函数调用顺序即可。(并不是bug)亲测可以哦:

    <body>
        <ul class="multi_ul">
            <li id="li1"></li>
            <li id="li2">同时运动</li>
            <li id="li3">不要移开,会有惊喜&nbsp;&nbsp;:)<br/>链式运动</li>
        </ul>
    </body>
    body, div, span{
                margin: 0px;
            }
    
            .multi_ul li{
                border: 5px solid blue;
                width: 200px;
                height: 100px;
                background-color: yellow;
                margin-bottom: 20px;
            }
    
            #li2, #li3{
                font-size: 12px;
                filter: alpha(opacity:30);/* IE8之前 */
                opacity: 0.3;
            }
    
            #li3{
                border: 10px solid black;
            }
                var li2 = document.getElementById('li2');
                //移入时,宽高同时运动,透明度随后运动
                UtilJS.EventUtil.addBubblingHandler(li2, "mouseover", function(){
                    UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "width", 400, 30, function(){
                        UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "fontSize", 48, 100);
                    });
                    UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "height", 400, 30);
                });
                //移出时,透明度先运动,宽高再同时运动
                UtilJS.EventUtil.addBubblingHandler(li2, "mouseout", function(){
                    UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "fontSize", 12, 100, function(){
                        UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "width", 200, 30);
                        UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed(li2, "height", 100, 30);
                    });
                });
    1. 舍去了老师的flag标志和json的使用;

    2. 主要缺点是:定时器绑定的有点多,一起运动的时候,耗内存(不过,最后都clear掉了);

  • 风_起
    2016-04-21 14:33:05

    舍去了flag的判断和json的使用;

    在实际使用的时候:多次调用UtilJS.AnimationUtil.changeElementStyleAtVariableSpeed()达到同时运动的效果;

    目测:该代码在同时运动的时候加入链式运动,有bug

JS动画效果

通过本课程JS动画的学习,从简单动画开始,逐步深入各种动画框架封装

113920 学习 · 1502 问题

查看课程

相似问题