首页 > 代码库 > 【转】2D动画:view的Matrix

【转】2D动画:view的Matrix

转载地址:http://blog.csdn.net/flowingflying

上学习的小例子是从左上角进行扩展动画,如果我们需要在中心进行扩展,相关的代码如下:

public class ViewAnimation1 extends Animation{
    private float centerX,centerY; 
    
    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) { 
        super.initialize(width, height, parentWidth, parentHeight); 
        centerX =  width/2.0f;
        centerY = height/2.0f;
        setDuration(2500);
        setFillAfter(true);
        setInterpolator(new LinearInterpolator());        
    }
   
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
        final Matrix matrix = t.getMatrix();
        Log.v("WEI","orignal matrix  " + matrix);
        matrix.setScale(interpolatedTime, interpolatedTime); 
        matrix.preTranslate(-lastPointX, -lastPointX); 
        matrix.postTranslate(centerX, centerY);

        Log.v("WEI"," target matrix  " + matrix); 
    }
}

矩阵

这里动画代码较之一开始的小例子有些令人困惑,需要先弄明白Matrix。从Android的reference和例子的LogCat跟踪,我们知道Matrix是一个3×3的矩阵,具体为:

而通过getMatrix()获得的是View没有发生动画变化的矩阵,即单位矩阵:

赋值操作

setScale()、setXXX()表示直接设置矩阵。执行matrix.setScale(interpolatedTime,interpolatedTime)后就获得下左图的view,我们需要进一步将移动位置,移动到下右图。

setXXX()相当于赋值操作。赋值的操作有以下:

matrix.reset() :设置为单位矩阵
matrix.setScale() :如上左图,以(0,0)为支点进行缩放
matrix.setTranslate()
matrix.setRotate()
matrix.setSkew()

乘操作:前乘和后乘

如果我们在setScale()后,进行setTranslate()操作,等于进行了两次赋值,最终值是后面的赋值,也就是前面setScale()无效。我们将看到的是整个view的移动,没有缩放效果。为此需要使用preXXX()和postXXX()的操作。在数学上是矩阵的计算,pre表示在作为前面的参数乘以一个矩阵,即M’=M*other,M为前乘;post表示作为后面参数乘一个矩阵M’=other*M,M为后乘,而set表示设置矩阵M=other。在图像处理上,pre表示先进行某个图像处理,接着是set的图像处理,最后是post的图像处理。

要实现目标效果,我们也可以通过下面的方法:

final Matrix matrix = t.getMatrix();
matrix.setScale(interpolatedTime, interpolatedTime);
matrix.postTranslate(centerX*(1-interpolatedTime), centerY*(1-interpolatedTime));

在图像处理上,先进行缩放,如左图,然后平移到右图位置。在数学上,也很容易证明

如果通过下面的方式:

final Matrix matrix = t.getMatrix();
matrix.setScale(interpolatedTime, interpolatedTime);
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);

在图像上,先将图像移动(-centerX,-centerY),相当将中心点方在(0,0)的位置上,然后缩放,最后将中心点移动到(centerX,centerY),如图所示:

在数学上也和容易证明:

或者

Matrix运算真是神奇,事实上,layout动画也是通过Matrix类来实现的。

矩阵计算

Matrix类还提供了直接矩阵计算方式。Matrix a=new Matrix()相当于创建一个单位矩阵。

a.set(b),就是赋值a = b;

a.preConCat(b),相当于前乘,即 a=a×b;

a.postConCat(b),相当于前乘,即 a=b×a;

c.setConcat(a,b),相当于c=a×b;

对于例子,我们可以设置3个矩阵,分别表示3种图形效果;

Matrix m1 = new Matrix();
m1.setScale(interpolatedTime, interpolatedTime); 

Matrix m2 = new Matrix();
m2.setTranslate(-centerX, -centerY); 

Matrix m3 = new Matrix();
m3.setTranslate(centerX, centerY);

要实现同样的例子效果,可以:

//matrix = m1
matrix.preConcat(m2);   //matrix = matrix * m2 = m1 * m2;
matrix.postConcat(m3); //matrix = m3 * matrix = m 3 * (m1* m2) = m3 * m1 *m2;

或者

// matrix = m1 * m2;
matrix.setConcat(m3, matrix); //matrix = m3 * matrix = m3* (m1* m2) = m3 * m1 * m2;