使用同一个封装的动画函数,当我们传入‘o’的时候,表示要设置透明度,但是ie8以下透明度是使用filter:alpha(opacity=xxx);来实现的,所以这里要对ie做个兼容。

首先对传参设置以下:

$('#pox').click(function() {
    $('#box').animation({
        'attr': 'o',
        'start': 30,
        'end': 100,
        'step': 7,
        'type' : 0
    })
});

我们先不设置缓动,attr传入o,起步的透明度为30,最终值为100,表示从透明到不透明,传值的时候要传入整数,js对小数有一些支持上的问题,所以后续的传值都尽量使用整数。

我们先对attr做个判断

对之前的attr判断改为:

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

连续三元判断。

初始值start判断

既然你传入的是透明度,那么起始值start也要改,之前的start是判断如果传入有值,那么就是传入的值+‘px’单位,但是透明度没有单位,所以start也要做个判断。

var start = obj['start'] != undefined ? obj['start'] :
    attr == 'opacity' ? getOpacity() : parseInt(getStyle(element, attr));

这里三元判断,如果有值,就使用这个传入的值,没有的话就判断attr是否为opacity,如果是,调用getOpacity函数获取opacity值,不是则使用之前的方法获取计算后的值。

跨浏览器获取opacity

filter:alpha(opacity=xxx);是ie8及以下使用的,ie9以上及其他浏览器直接使用opacity,于是:

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 getStyle(element, 'opacity') * 100;
    }
}

之前做的ua判断派上了用场,直接判断ie的版本,如果是小于或者等于8,就获取计算后的filter,然后通过正则,将匹配值赋值给数组s,然后通过小标的方式,将正则分组中的数字return出去,但是要注意,return的这个s[1]是一个string类型,所以通过parseInt()转换成数字。

如果是其他浏览器,获取opacity即可,但是获取的是0.xx这种,所以要乘以100获得整值,方便操作。

然后增量的问题了

增量判断

因为我们start的时候传入的参数是整数,然后增量自然也是传入整数,获取opacity也是返回的整数,所以增量没有问题。

设置初始值

之前我们设置初始值因为只针对移动和大小,使用了px单位,但是这里透明度是没有px单位的,所以要做个判断了

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

这里判断是透明度就实用透明度的赋值方法给元素赋值,不是则之前的方法。

设置每次增加量

目前我们没有设置缓动,所以这要设置好匀速移动的间歇调用即可

同样,透明度的设置方法和移动不同,所以要另写一个if

var timer = setInterval(function() {

    if (type == 'buffer') {
        step = attr == 'opacity' ? (end - getOpacity()) / speed : (end - parseInt(getStyle(element, attr))) / speed;
        step = (step > 0) ? Math.ceil(step) : Math.floor(step);
    }
    if (attr == 'opacity') {
        var temp = getOpacity();
        if (step > 0 && Math.abs(temp - end) <= step) {
            setOpacity();
        } else if (step < 0 && parseInt(temp - end) <= Math.abs(step)) {
            setOpacity();
        } else {
            element.style.filter = 'alpha(opacity=' + parseInt(temp + step) + ')';
            element.style[attr] = (temp + step) / 100;
        }
    } 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)

if判断如果是透明opacity,就这样,else则使用之前的方法。

是透明,也一样要判断step步进的值,如果是<0表示从不透明到透明,并且最终的透明度 - 当前的透明度 <= step步进的值,那么就调用setOpacity方法,这个方法和之前的步进一样,让设置的值直接等于最终end值,解决超出回弹的问题,并且删除间歇调用,其他都一样,这里新增加了一个step== 0,事实上step等于0之前就已经被判断了,根本不会再运行,这里加了个==是做个保险。

setOpacity()方法:

function setOpacity() {
    element.style.filter = 'alpha(opacity=' + parseInt(end) + ')';
    element.style[attr] = parseInt(end) / 100;
    clearInterval(timer);
}

ie8及以下的方法和其他浏览器的方法。

以上就差不多可以了,但是缓动还没有做,其实到这里就很简单了。

缓动修改

if (type == 'buffer') {
    step = attr == 'opacity' ? (end - getOpacity()) / speed : (end - parseInt(getStyle(element, attr))) / speed;
    step = (step > 0) ? Math.ceil(step) : Math.floor(step);
}

如果要使用缓动,step使用三元运算判断,如果attr是opacity,那么就让end减去getOpacity()获取的元素opacity值,然后除以倍速speed,如果attr不是opacity,那么就使用之前的方法,其他的都一样。

整合:

//设置动画
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 time = obj['time'] != undefined ? obj['time'] : 30;
        var step = obj['step'] != undefined ? obj['step'] : 20;
        var add = obj['add'];
        var end = obj['end'];
        var speed = obj['speed'] != undefined ? obj['speed'] : 6;
        var type = obj['type'] == 0 ? 'constant' : obj['type'] == 1 ? 'buffer' : 'buffer';
        
        if(add != undefined && end == undefined) {
            end = add + start;
        }else if (add == undefined && end == undefined) {
            throw new Error('alter增量或target目标量必须传一个!');
        }
        if(start > end) step = -step;
        if(attr == 'opacity') {
            element.style.opacity = parseInt(start) / 100;
            element.style.filter = 'alpha(opacity=' + parseInt(start) +')';
        }else {
            element.style[attr] = start + 'px';
        }
        
        clearInterval(window.timer);
        timer = setInterval(function () {
            if(type == 'buffer') {
                step =  attr == 'opacity' ? (end - getOpacity())/speed :
                        (end - parseInt(getStyle(element, attr)))/speed;
                step = (step > 0) ? Math.ceil(step) : Math.floor(step);
            }
            
            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 = parseInt(temp + step) / 100;
                    element.style.filter = 'alpha(opacity=' + parseInt(temp + step) + ')'
                }
            }else {
                if (step == 0) {
                    setTarget();
                }else if(step > 0 && Math.abs(parseInt(getStyle(element, attr)) - end) <= step) {
                    setTarget();
                }else if(step < 0 && (parseInt(getStyle(element, attr)) - end) <= Math.abs(step)) {
                    setTarget();
                }else {
                    element.style[attr] = parseInt(getStyle(element, attr)) + step + 'px';
                }
            };
        },time);
        
        function setTarget() {
            element.style[attr] = end + 'px';
            clearInterval(timer);
        }
        function setOpacity() {
            element.style.opacity = parseInt(end) / 100;
            element.style.filter = 'alpha(opacity=' + parseInt(end) + ')';
            clearInterval(timer);
        }
        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;
}

调用:

$('#pox').click(function() {
    $('#box').animation({
        'attr': 'o',
        'start': 30,
        'end': 100,
        'step': 7,
        'type': 1

    })
});

预览图:

JS动画之透明度

分类: JavaScript 标签: opacity

评论

全部评论 4

  1. 吃枣药丸
    吃枣药丸
    Google Chrome Windows 10
    学到新技术,谢谢大佬
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @吃枣药丸你这样说我无法相信
      1. 吃枣药丸
        吃枣药丸
        Google Chrome Windows 10
        1. d
          d
          FireFox Windows 10
          @吃枣药丸哦!是吗?

目录