正在加载中

最后更新于 2018年12月21日

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

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

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) {}。

以上完成。

  • weixiao kaixin tushetou jingkong deyi fanu liezui liuhan daku ganga bishi nanguo lihai qian yiwen numu tu yi haixiu se fadai minyan hehe henkaixin huaji biyiyan kuanghan maimeng shui xiaku penqi zhangzui pen aini ye niu laji ok chigua renshi kongbu shuai xiaoxiese touxiao huaixiao jingnu chihuai kaisang xiaoku koubi zhuangbi lianhong kanbujian shafa zhijing xiangjiao dabian yaowan redjing lazhu rizhi duocang chixigua hejiu xixi xiaopen goukun xiaobuchu shenme wusuowei guancha lajing chouyan xiaochi bie zhadanzui zhadanxiao

登录