先修缮一下百度分享栏的自动居住问题。

之前是每次刷新会自动居中,这里我们要改为当用户滑动时也会自动居中。

addEvent(window,'scroll',function(){
    $('#share').css('top',getScroll().height + (getInner().height - parseInt(getStyle($('#share').first(),'height')))/2 + 'px');
});

//跨浏览器获取scroll大小
function getScroll() {
    return {
        width : document.body.scrollLeft != 0 ? document.body.scrollLeft : document.documentElement.scrollLeft,
        height : document.body.scrollTop != 0 ? document.body.scrollTop : document.documentElement.scrollTop
    }
};

分享栏之前就以及算好了可视高度自动居中的高度,那么只要加上被滚动后距离就可以达到居中的效果,在window下的scroll事件中每次触发都是加上对应的scroll高度,以此达到滚动自动居中。

改为动画效果:

//设置百度分享菜单自动居中
addEvent(window, 'scroll', function() {
    $('#share').animation({
        'attr': 'y',
        'end': getScroll().height + (getInner().height - parseInt(getStyle($('#share').first(), 'height'))) / 2
    });
});

同步动画:

同步动画需要新传入一个键值对参数,这个键值对里面保存着需要同时运行的动画参数。

animation({
   mul {
     'x' :  300,
     'y' :  300
   }
})

这个mul就表示需要同步运行的动画有x轴移动到300,y轴移动到300。

为此animation封装库中需要新建一个变量用于保存这个mul参数,而且在判断的时候,end的值要等于mul中的300。

同步运行需要在同一个timer超时调用中,为此只能通过for语句循环这个mul,里面有几个参数,就循环调用几次,在同一个timer中,相同的time时间内。

于是:

调用函数

//设置动画
$('#pox').click(function() {
    $('#box').animation({
        'attr': 'x',
        'end': -100,
        'step': 7,
        'type': 1,
        'mul': {
            'o': 30,
            'h': 500
        }

    })
});

同时让透明度为30,高度500px。

封装库

//设置动画
Base.prototype.animation = function(obj) {
    for (var i = 0; i < this.arr.length; i++) {
        var element = this.arr[i];
        var attr = obj['attr'] == 'x' ? 'left' : obj['attr'] == 'y' ? 'top' :
            obj['attr'] == 'w' ? 'width' : obj['attr'] == 'h' ? 'height' :
            obj['attr'] == 'o' ? 'opacity' : 'left';
        var start = obj['start'] != undefined ? obj['start'] :
            attr == 'opacity' ? getOpacity() :
            parseInt(getStyle(element, attr));
        var step = obj['step'] != undefined ? obj['step'] : 20;
        var time = obj['time'] != undefined ? obj['time'] : 30;
        var add = obj['add'];
        var end = obj['end'];
        var type = obj['type'] == 0 ? 'constant' : obj['type'] == 1 ? 'buffer' : 'buffer';
        var speed = obj['speed'] != undefined ? obj['speed'] : 6;
        var mul = obj['mul'];

        if (add != undefined && end == undefined) {
            end = add + start;
        } else if (add == undefined && end == undefined && mul == undefined) {
            throw new Error('alter增量或target目标量必须传一个!');
        }
        if (start > end) step = -step;

        if (attr == 'opacity') {
            element.style.opacity = start / 100;
            element.style.filter = 'alpha(opacity=' + start + ')';
        } else {
            element.style[attr] = start + 'px';
        }

        if (mul == undefined) {
            mul = {};
            mul[attr] = end;
        }

        clearInterval(element.timer);
        element.timer = setInterval(function() {
            for (var i in mul) {
                attr = i == 'x' ? 'left' : i == 'y' ? 'top' :
                    i == 'w' ? 'width' : i == 'h' ? 'height' :
                    i == 'o' ? 'opacity' : i != undefined ? i : 'left';
                end = mul[i];

                if (type == 'buffer') {
                    step = attr == 'opacity' ? (end - getOpacity()) / speed :
                        (end - parseInt(getStyle(element, attr))) / speed;
                    step = (step > 0) ? Math.ceil(step) : Math.floor(step);
                }
                //document.getElementById('dox').innerHTML += getStyle(element, attr) + 'px' + '<br/>';
                if (attr == 'opacity') {
                    if (step == 0) {
                        setOpacity();
                    } else if (step > 0 && Math.abs(getOpacity() - end) <= step) {
                        setOpacity();
                    } else if (step < 0 && (getOpacity() - end) <= Math.abs(step)) {
                        setOpacity();
                    } else {
                        var temp = getOpacity();
                        element.style.opacity = (temp + step) / 100;
                        element.style.filter = 'alpha(opacity=' + (temp + step) + ')'
                    }
                } else {
                    if (step == 0) {
                        setAttr();
                    } else if (step > 0 && Math.abs(parseInt(getStyle(element, attr)) - end) <= step) {
                        setAttr();
                    } else if (step < 0 && (parseInt(getStyle(element, attr)) - end) <= Math.abs(step)) {
                        setAttr();
                    } else {
                        element.style[attr] = parseInt(getStyle(element, attr)) + step + 'px';
                    }
                };
            };
        }, time);

        function setAttr() {
            element.style[attr] = end + 'px';
            clearInterval(element.timer);
            if (obj.fn != undefined) obj.fn();
        }

        function setOpacity() {
            element.style.opacity = parseInt(end) / 100;
            element.style.filter = 'alpha(opacity=' + parseInt(end) + ')';
            clearInterval(element.timer);
            if (obj.fn != undefined) obj.fn();
        }

        function getOpacity() {
            if (system.ie <= 8) {
                var op = getStyle(element, 'filter');
                var s = [];
                if (op.match(/opacity=([\d]+)/)) {
                    s = op.match(/\=([\d]+)/);
                } else {
                    throw new Error('ie8一下没有获取到filter中的opacity值');
                }
                return parseInt(s[1]);
            } else {
                return parseFloat(getStyle(element, 'opacity')) * 100;
            }
        }
    }
    return this;
}

首先var mul = obj[‘mul’];保存传入的mul参数。

然后在if判断是否传入值得时候加上 mul != undefined 的条件。

在超时调用timer中,通过for... in.. 语句枚举出mul中的键值对的名称,然后判断i是什么值,再将对应的值附给attr。

end的值就直接mul[i]即可获得。

然后将step步进和修改css的代码当如这个for...in..语句中,这样每次for循环的时候就会运行一次对应的修改css代码,加上前面我们已经将attr和end的值改为mul传入的值,最后因为是在同一个timer中,同一段时间,于是达到了同步运行动画的效果。

但是这样我们导致单独设置动画,不用mul就是失效,因为我们在timer中重置了attr和end的值,所以在创建超时调用之前还要做个判断。

if (mul == undefined) {
    mul = {};
    mul[attr] = end;
}

如果mul没有值,说明就是单次效果,那么我们将mul重新赋值为一个对象,然后通过键值对的方式设置参数即可。

但是这样设置的attr实际上已经是完整的名称了,如width,height等等,所以在超时调用中i在判断的时候加上,如果前面的都不是,而且i也不是undefined,那么就等于这个i就可以了,那么这个i就是完整的名称。

那么之前的var attr = xxx 也可以加上这句话,这样我们既可以通过缩写设置参数,也可以通过写完整名称来设置。

var attr = obj['attr'] == 'x' ? 'left' : obj['attr'] == 'y' ? 'top' :
    obj['attr'] == 'w' ? 'width' : obj['attr'] == 'h' ? 'height' :
    obj['attr'] == 'o' ? 'opacity' : obj['attr'] != undefined ? obj['attr'] : 'left';

以上动画就完成了,下面我们综合测试一下:

调用函数:

//设置动画
$('#pox').click(function() {
    $('#box').animation({
        'attr': 'x',
        'end': -100,
        'step': 7,
        'type': 1,
        'mul': {
            'o': 30,
            'h': 500
        },
        'fn': function() {
            $('#box').animation({
                'attr': 'x',
                'end': 500
            })
        }

    })
});

效果图:

这里我们可以看到同步和队列都可以运行,而且互不影响,但是单个设置会被同步设置覆盖,因为我们之前做了判断,if (mul == undefined) {}。

以上完成。

分类: JavaScript 标签: 同步动画

评论

暂无评论数据

暂无评论数据

目录