正在加载中

最后更新于 2018年12月16日

使用同一个封装的动画函数,当我们传入‘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动画之透明度

  • 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
  1. 吃枣药丸

    发表于:
    来自 Google Chrome 70 in windows 10

    学到新技术,谢谢大佬

    1. 木灵鱼儿

      发表于:
      来自 FireFox 63 in windows 10
      @吃枣药丸

      你这样说我无法相信

      1. 吃枣药丸

        发表于:
        来自 Google Chrome 70 in windows 10
        @木灵鱼儿

        真的!

        1. d

          发表于:
          来自 FireFox 63 in windows 10
          @吃枣药丸

          哦!是吗?

登录