zoukankan      html  css  js  c++  java
  • Android开发之Tween(补间动画)

    在android中动画主要有三种,①帧动画(http://blog.csdn.net/dmk877/article/details/45893017)这篇文章已经详细的进行了讲解,②补间动画这也是这篇博客将要讨论的,③属性动画后续的文章中会和大家一起讨论。

    Tween动画的分类

    首先来了解下补间动画的分类,在android中补间动画可以分为四类:alpha(渐变)、scale(缩放)、translate(位移)、rotate(旋转)。在这四种动画里每种动画拥有它的独有的属性的同时又拥有相同的属性,其中

    alpha:渐变透明度动画效果

    scale:渐变缩放动画效果

    translate:渐变位置移动动画效果

    rotate:渐变旋转动画效果,这四种动画能够分别带来不同的效果体验,又能混合在一起完成酷炫的动画效果。
    接下来我们就逐一详细的来学习这四种Tween动画

    1、roate动画,旋转动画

    在上面我们提到四种Tween动画都有其独有的属性又有其从Animation类继承的公共的属性,我们对这四种动画的讨论也将从两方面:一方面是独有的属性,另一方面是从Animation类继承的属性,从Animation这个类继承的属性用法都一样,这里以roate动画为例讨论一遍就行了。
     
    1.1 独有属性
    android:fromDegrees:动画开始时旋转的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
    android:toDegrees: 动画结束时旋转到的角度位置,float类型,正值代表顺时针方向度数,负值代码逆时针方向度数
    android:pivotX:旋转点X轴坐标,float类型,可以是数值、百分数、百分数p三种样式,比如50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标,如果是50%;表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;如果是50%p,那么就是表示在当前控件的左上角加上父控件宽度的50%做为旋转点X坐标。
    android:pivotY:旋转点Y轴坐标,取值及意义跟android:pivotX一样。
     
    1.2 从Animation类继承的属性
    android:duration:动画执行的时间,以毫秒为单位
    android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态
    android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
    android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍,这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
    android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
    android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹 起等等
     
    1.3 roate动画的各属性讲解
     
    1.3.1 fromDegress、toDegress属性
    fromeDegress和toDegress这两个属性很好理解fromDegress表示从动画开始时旋转的角度,而toDegress当然就表示动画结束时旋转的角度了,如果你还不能理解透彻,相信下面的两个小例子可以帮助你,首先来看看运行效果。
    它的xml配置文件如下:
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:duration= "1000">  
    </rotate>  

    最后XML文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?这是就要借助AnimationUtils这个类了,只需调用如下代码即可:

    Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate);  
    ivGirl.startAnimation(animation);  
    从运行效果我们可以看到它从起始的0度旋转了360度。另外我们还能得出一个结论:默认的旋转的起始点是View的左上角顶点为起始点。需要注意的是这里开始旋转角度fromDegree与结束时的旋转角度toDegrees都是是相对于起始位置而言的,什么意思呢?看下面这个例子你就会彻底理解。
    我们修改下xml配置文件,修改如下:
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "60"  
             android:toDegrees= "90"  
             android:fillAfter= "true"  
             android:duration= "10000">  
    </rotate>  
    运行效果图:
    在上述xml中我们设置的fromDegress是60度,toDegress是90度,从运行效果中可以看出点击运行按钮后,View首先立即旋转了60度作为旋转动画的起始位置,之后又旋转了30度到了90度,所以大家一定要理解清楚这里的toDegress是相对于起始位置而言的。
     
    1.3.2 pivotX、pivotY
    在上面我们也提到"pivotX"表示旋转点X轴坐标,也就是我们的View是以哪个点为基准而旋转的,它的值可以是数值、百分数、百分数p 三种样式,比如50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为旋转点X坐标;如果是50%表示在当前控件的左上角加上自己宽度的50%做为旋转点X坐标;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为旋转点X坐标。
    "pivotY"属性与"pivotX"属性一样。接下来就分别结合实例来详细理解下这三种取值吧。
    • 取值为数值
    • <?xml version="1.0" encoding= "utf-8"?>  
      <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
               android:fromDegrees= "0"  
               android:toDegrees= "360"  
               android:pivotX= "75"  
               android:pivotY= "125"  
               android:duration= "10000">  
      </rotate>  
    从上面的解释可以知道,这里的旋转的X点的坐标是在原点的基础之上增加75px,而Y点的坐标是在原点的基础之上增加125px。由于图片的高度和宽度分别为150、250,运行在这是480*320的模拟器此时1dp=1px)所以我们设置的pivotX=75,pivotY=125也就刚好在图片的正中间,运行效果如下
                    
    注意在这张美女图片的下巴上有个小白点,这个小白点是图片的中心位置。我们发现它的旋转点就是这个View的中心点。
    • 取值为百分数
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             android:duration= "10000">  
    </rotate>  

    pivotX的值当取百分数时表示在原点坐标(View的左上角的那个点)的基础之上加上自己的宽度,那么当取50%时,表示在原点坐标的基础上加上的自己宽度的50%也就是图片的正中心,为了防止大家审美疲劳我换了张美女图片,中间的小白点不是特别明显,运行效果如下:

    我们发现它的旋转的中心就是View的中心。
    • 取值为百分数后面加p
    取值为百分数后加p表示旋转点在原点的基础之上加上父控件的百分值。如pivotX取值为50%p就表示旋转点的x坐标在原点基础之上父控件宽度的50%。经计android:pivotX="23%p",android:pivotY="26%p"时旋转的点处于View的中间,480*26/100约等于125,即旋转点的Y坐标在坐标原点的基础之上加上125与(1)类似
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:pivotX= "23%p"  
             android:pivotY= "26%p"  
             android:duration= "10000">  
    </rotate>  
    运行效果与上面一样,就不再上图了。
     
    1.3.3 android:fillAfter
    这个属性设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,true表示停留在最后一帧,false表示不停留在最后一帧
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "300"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             android:fillAfter= "true"  
             android:duration= "1000">  
    </rotate>  
    运行效果:
    上面的xml属性动画的配置中,我们将fillAfter的值设置为true,可以看到它停留在了最后一帧。

    1.3.4 android:fillBefore
    它表示View动画结束时是否会停留在动画开始的状态
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "300"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             android:fillEnabled= "true"  
             android:fillBefore= "true"  
             android:duration= "1000">  
    </rotate>  
    运行效果:
    可以看到图片旋转300度后又回到了最开始的状态。
     
    1.3.5 android:repeatMode
    重复类型,取值为reverse|restart,reverse:表示倒序回放,restart:表示重新放一遍,这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             android:repeatMode= "restart"  
             android:repeatCount= "2"  
             android:fillEnabled= "true"  
             android:fillBefore= "true"  
             android:duration= "1000">  
    </rotate>  
    reverse:表示倒序回放,restart:表示重新放一遍
    android:repeatMode="restart"                   android:repeatMode="reverse"
                                 
    在上述xml文件配置中我们将repeatCount设置为2,从运行效果可以看出两者的区别restart是连续播放,而reverse播放一遍后倒序播放了一遍。
     
    1.3.6 android:repeatCount
    动画重复的次数(注意是重复的次数),可以是你想循环播放的次数数值,也是可以取值infinite:表示无限循环,这个属性在上面也介绍用到了,就不再上图片了。
     
    2 、Alpha动画(渐变透明度动画)
     
    2.1 Alpha的特有属性
    android:fromAlpha:动画开始时的透明度,变化范围为0.0-1.0,0.0表示完全透明,1.0表示完全不透明
    android:toAlpha:动画结束是的透明度,变化范围和意义同上。
    其实它的意义很好理解,一个View透明度变化,肯定是从一个透明度变为另一个透明度。这样就需要两个属性fromAlpha和toAlpha,这个变化的过程是android自动帮我们实现的,也就是说假如从完全透明,到完全不透明这中间的过程是谷歌工程师为我们提供好的,当然我们也可以改变。
    <?xml version="1.0" encoding= "utf-8"?>  
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"  
            android:fromAlpha= "0.0"  
            android:toAlpha= "1.0"  
            android:repeatCount= "2"  
            android:duration= "3000"  
            android:fillAfter= "true" >  
    </alpha>  
    在上面的xml配置中我们设置了图片的透明度从0逐渐变化到1,可以看到运行效果从完全不透明变化到完全透明。
     
    2.2 从Animaton类继承的属性
    android:duration:动画执行的时间,以毫秒为单位
    android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,false?
    android:fillBefore:与fillEnabled相同
    android:fillAfter:true|false,true:动画结束时,将保持动画最后时的状态
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍
    这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
    android:repeatCount:动画重复的次数,可以是你想循环播放的次数,也是可以是infinite:表示无限循环
    android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
    这些公共的属性我们在roate动画中已经通过效果一一解释过了,就不再重复演示了。
       
    3、translate(位移动画)
     
    3.1 位移动画独有的属性
    android:fromXDelta:起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,具体意义在roate已经演示过。
    android:fromYDelta:起始点Y坐标,可以是数值、百分数、百分数p三种样式。
    android:toXDelta:结束点X坐标
    android:toYDelta:结束点Y坐标
    <?xml version="1.0" encoding= "utf-8"?>  
    <translate  
        xmlns:android ="http://schemas.android.com/apk/res/android"   
        android:fromXDelta="0"  
        android:fromYDelta="0"  
        android:toXDelta="200"  
        android:toYDelta="300"  
        android:duration="5000">  
    </translate>  
    运行效果:
     
    可以看到美女逐渐的离开了我们的视线。
     
    3.2 从Animation类继承的属性
    android:duration:动画执行的时间,以毫秒为单位
    android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,
    android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义
    默认值是true,视图会停留在动画开始的状态
    android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
    android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
    android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等
     
    4、scale缩放动画
     
    4.1 独有属性
    android:fromXScale起始的X方向上相对自身的缩放比例,类型float,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍
    android:toXScale:结尾的X方向上相对自身的缩放比例,类型float
    android:fromYScale:起始的Y方向上相对自身的缩放比例,类型float
    android:toYScale:结尾的Y方向上相对自身的缩放比例,类型float
    android:pivotX: 缩放起点X轴坐标,可以是数值、百分数、百分数p ,具体意义roate中已经演示
    android:pivotY:缩放起点Y轴坐标,取值及意义与pivotX一样
    <?xml version="1.0" encoding= "utf-8"?>   
    <scale xmlns:android="http://schemas.android.com/apk/res/android"  
           android:fromXScale= "2.0"  
           android:toXScale= "1.0"  
           android:fromYScale= "2.0"  
           android:toYScale= "1.0"  
           android:pivotX= "50%"  
           android:pivotY= "50%"  
           android:duration= "5000">  
        
    </scale>  
    运行效果:
    可以清楚的看到这张图片先是放大了两倍然后逐渐恢复原状。
     
    4.2 从Animation类继承的属性
    android:duration:动画执行的时间,以毫秒为单位
    android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态
    android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
    android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为它的前提是重复,即重复播放时的播放类型。
    android:repeatCount:动画重复的次数(注意是重复的次数),可以是你想循环播放的次数,也是可以是infinite:表示无限循环
    android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
     
    5、set标签的使用
     
    到这里可能有的同学会说动画太单调,其实学好Tween动画你能做出好多比较酷炫的动画,这就要用到set标签了从它的名字我们也能够猜出来它是干什么用的,它就是一组动画的集合,也就是说我们可以让一个View同时执行多个动画,set标签自已是没有属性的,他的属性都是从Animation继承而来,但当它们用于Set标签时,就会对Set标签下的所有子控件都产生作用。
    它所拥有的属性我们上面也介绍到了
    android:duration:动画执行的时间,以毫秒为单位
    android:fillEnabled:true|false,true:动画结束时还原到开始动画前的状态,false?
    android:fillBefore:与fillEnabled相同
    android:fillAfter:true|false,true:动画结束时,将保持动画最后时的状态
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
    android:repeatCount:动画重复的次数,可以是你想循环播放的次数,也是可以是infinite:表示无限循环
    android:interpolator:设定的插值器,它主要用来为动画设置一些特殊的效果,比方说:加速运动、减速运动、动画结束的时候弹起等等。
    接着们就来看一个组合动画吧
    xml文件
    <?xml version="1.0" encoding= "utf-8"?>  
    <set xmlns:android="http://schemas.android.com/apk/res/android"  
        android:fillAfter="true">  
         
        <alpha  
            android:fromAlpha= "0.0"  
            android:toAlpha= "1.0"  
            android:duration= "3000" />  
         
        <scale  
            android:fromXScale= "0.0"  
            android:toXScale= "1.0"  
            android:fromYScale= "0.0"  
            android:toYScale= "1.0"  
            android:pivotX= "50%"  
            android:pivotY= "50%"  
            android:duration= "3000" />  
         
        <rotate  
            android:fromDegrees= "0"  
            android:toDegrees= "720"  
            android:pivotX= "50%"  
            android:pivotY= "50%"  
            android:duration= "3000"/>  
         
         <translate  
            android:startOffset= "3000"  
            android:fromXDelta= "0"  
            android:fromYDelta= "0"  
            android:toXDelta= "85"  
            android:toYDelta= "0"  
            android:duration= "1000" />  
          
        <alpha  
            android:startOffset= "4000"  
            android:fromAlpha= "1.0"  
            android:toAlpha= "0.0"  
            android:duration= "1000" />  
      
    </set> 
    我们用它来实现一个稍微酷炫点的动画
    可以看到这个组合动画展示了美女从出厂到离开的整个过程。
    接着来看下从Animation继承的几个属性的讲解
    android:duration:这个我相信不用多说了,就是整个动画执行的时间
    android:fillEnabled:默认值是false。如果是true,动画将会应用fillBefore值;否则,fillBefore的值会被忽略,transformation会在动画结束的时候被应用。(这个属性的出现是谷歌为了兼容之前的版本)
    android:fillBefore:如果fillEnabled的值为true,它的值才有意义,否则没有意义默认值是true,视图会停留在动画开始的状态
    android:fillAfter:设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,它的设置不受fillEnabled的影响
    android:repeatMode:reverse|restart,重复类型,reverse:表示倒序回访,restart:表示重新放一遍这个属性必须与repeatCount联合使用,因为牵扯到重复,即重复播放时的播放类型。
     
    6、interpolator插值器
     
    首先来看下官网给出的interpolator的定义:interpolaotor定义了动画变化的速率,它允许基础动画(alpha, scale, translate, rotate)加速,减速,重复变化等等。在补间动画中,我们一般只定义关键帧(首帧和尾帧),然后由系统自动生成中间帧,生成中间帧的这个过程可以成为“插值”。插值器定义了动画变化的速率,提供不同的函数定义变化值相对于时间的变化规则,可以定义各种各样的非线性变化函数,比如加速、减速等。下面是几种常见的插值器:
    Interpolator对象 资源ID 功能作用
    AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速再减速
    AccelerateInterpolator @android:anim/accelerate_interpolator 加速
    AnticipateInterpolator @android:anim/anticipate_interpolator 先回退一小步然后加速前进
    AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 先回退一小步然后加速前进,超出终点一小步后再回到终点
    BounceInterpolator @android:anim/bounce_interpolator 最后阶段弹球效果
    CycleInterpolator @android:anim/cycle_interpolator 周期运动
    DecelerateInterpolator @android:anim/decelerate_interpolator 减速
    LinearInterpolator @android:anim/linear_interpolator 匀速
    OvershootInterpolator @android:anim/overshoot_interpolator 快速到达终点并超出一小步最后回到终点
    怎么用它呢?它的用法也非常简单只需要在xml文件中加一句话就行了
    <?xml version="1.0" encoding="utf-8"?>  
    <translate   
        xmlns:android="http://schemas.android.com/apk/res/android"  
        android:interpolator="@android:anim/bounce_interpolator"   
        android:fromXDelta="0"  
        android:fromYDelta="0"  
        android:toXDelta="200"  
        android:toYDelta="300"  
        android:duration="5000">  
    </translate>  

    如果只简单地引用这些插值器还不能满足需要的话,我们要考虑一下个性化插值器。我们可以创建一个插值器资源修改插值器的属性,比如修改AnticipateInterpolator的加速速率,调整

    CycleInterpolator的循环次数等。为了完成这种需求,我们需要创建XML资源文件,然后将其放于/res/anim下,然后再动画元素中引用即可。我们先来看一下几种常见的插值器可调整的属性:

    <accelerateDecelerateInterpolator> 无
    <accelerateInterpolator> android:factor 浮点值,加速速率,默认为1
    <anticipateInterploator> android:tension 浮点值,起始点后退的张力、拉力数,默认为2
    <anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮点值,拉力的倍数,默认为1.5(2  * 1.5)
    <bounceInterpolator> 无
    <cycleInterplolator> android:cycles 整数值,循环的个数,默认为1
    <decelerateInterpolator> android:factor 浮点值,减速的速率,默认为1
    <linearInterpolator> 无
    <overshootInterpolator> 浮点值,超出终点后的张力、拉力,默认为2
    接下来就来看几个不是特别好理解的插值器的运行效果,没有演示到的,大家可以自己动手运行看看效果

    • anticipateInterploator

    先回退一小步然后加速前进

    <?xml version="1.0" encoding="utf-8"?>  
    <translate   
        xmlns:android="http://schemas.android.com/apk/res/android"  
        android:interpolator="@android:anim/anticipate_interpolator"  
        android:fromXDelta="0"  
        android:fromYDelta="0"  
        android:toXDelta="0"  
        android:fillAfter="true"  
        android:toYDelta="480"  
        android:duration="3000">  
    </translate>  
    运行效果:
    可以看到它先回退一段距离然后再加速前进。
    在上面我们也提到有几种插值器是支持对属性的调整的,我们就以anticipateInterploator为例,这时我们需要新建一个xml文件放置于/res/anim文件夹下,比如我们新建一个my_anticipate_interpolator.xml文件,它的内容如下:
    <?xml version="1.0" encoding="utf-8"?>    
    <anticipateInterpolator    
        xmlns:android="http://schemas.android.com/apk/res/android"    
        android:tension="4.0"/>   
    可以看到这里将tension的值改为了4,引用它的方法也非常简单如下:
    <?xml version="1.0" encoding="utf-8"?>  
    <translate   
        xmlns:android="http://schemas.android.com/apk/res/android"  
        android:interpolator="@anim/my_anticipate_interpolator"  
        。。。。。。>  
    </translate>  
    运行效果:
    可以明显的看出小球回退的距离要远一点。当然你也可以更改其他插值器的其它属性,从而符合自己的要求。
    • AnticipateOvershootInterpolator

    可以看到AnticipateOvershootInterpolator的运行效果先回退一小步然后加速前进,超出终点一小步后再回到终点。

    • BounceInterpolator

    可以看到在小球在最后阶段的效果是弹球效果。

    • OvershootInterpolator



    好了到这里关于四种Tween动画的讨论就结束了

    转载http://blog.csdn.net/dmk877/article/details/51912104

  • 相关阅读:
    详细版Jmeter随机参数的接口并发测试总结
    Windows下MQTT代理服务器的搭建
    关于使用elascticsearch的两个小技巧
    解决easyswoole的swServer_start_check: onTask event callback must be set at报错
    解决使用宝塔安装的swoole扩展,运行项目出现的3个常见问题
    浅谈一下ThinkPHP5.1实现事务嵌套的特性
    资源出现多个 "Access-Control-Allow-Origin"
    Mac 制作系统启动盘
    深入剖析分布式一致性共识算法
    分布式系统限流算法分析与实现
  • 原文地址:https://www.cnblogs.com/kelina2mark/p/7671320.html
Copyright © 2011-2022 走看看