Android 界面漩渦扭曲動效實現

背景:以前偶然看到優酷有相似的頁面切換動畫效果。因而本身也打算來實現下這樣的效果。java

動效說明:點擊界面中的任意位置,界面以點擊位置做爲中心點,開始以漩渦狀態,扭曲,收縮。直到消失。算法

直接上我實現的效果:canvas

 

一,方法原理說明:api

  1.  將頁面生成bitmap。
  2.  使用自定義View來繪製扭曲的圖像。 圖像繪製的時候使用的關鍵的api 是: canvas.drawBitmapMesh();

二,實現細節說明:ide

    1.  生成頁面Bitmap: 優先使用drawingCache , 若是沒有再建立bitmap 對象。動畫

public static Bitmap createBitmapFromView(View view) {
        if (view instanceof ImageView) {
            Drawable drawable = ((ImageView) view).getDrawable();
            if (drawable != null && drawable instanceof BitmapDrawable) {
                return ((BitmapDrawable) drawable).getBitmap();
            }
        }
        view.clearFocus();
        Bitmap bitmap = view.getDrawingCache();
        if(bitmap != null) {
            return bitmap;
        }
        
        bitmap = createBitmapSafely(view.getWidth(),
                view.getHeight(), Bitmap.Config.ARGB_8888, 1);
        if (bitmap != null) {
            synchronized (sCanvas) {
                Canvas canvas = sCanvas;
                canvas.setBitmap(bitmap);
                view.draw(canvas);
                canvas.setBitmap(null);
            }
        }
        return bitmap;
    }

    public static Bitmap createBitmapSafely(int width, int height, Bitmap.Config config, int retryCount) {
        ...
    }

 

    2. 關於自定義控件 VortexView 。 主要是再onDraw(Canvas ) 方法中使用rootView 生成的Bitmap 經過canvas.drawBitmapMesh 方法來繪製扭曲的圖像。(最開始個人方案是支持在native 中,對圖片進行像素級別的修改。 雖然成功了,可是效率卻很慢。)spa

關於API drawBitmapMesh 能夠參考一下這篇博文:使用drawBitmapMesh方法產生水波設計

期原理猜想應該是使用了opengl 中紋理,座標變換映射的技術。(只是猜想)rest

drawBitmapMesh使用方法:將原始圖片分割成爲M行,N列。 並計算得出原始的每一個交點再二維空間內的座標。 坐上角爲(0,0)點。 水平向右爲X正方向。 垂直向下爲Y正方向。  使用漩渦算法,計算每一幀下,原始頂點(線的交點)在當前時刻下的座標位置。即生成的局部變量ve[]; 這樣界面就能顯示出圖像被扭曲的動畫。code

固然:分割的行列越多,效果就會越好。

public class VortextView extends View {
...

 @Override
    public void onDraw(Canvas canvas) {
        if (destBitmap != null) {
            int mswd = mesh.getMeshWidth();
            int msht = mesh.getMeshHeight();
            float[] ve = mesh.getVertices();

            if (rect != null) {
                int count = canvas.save();
                canvas.translate(rect.left, rect.top);
                canvas.drawBitmapMesh(destBitmap, mswd, msht, ve, 0, null, 0, null);
                canvas.restoreToCount(count);
            } else {
                canvas.drawBitmapMesh(destBitmap, mswd, msht, ve, 0, null, 0, null);
            }

//            mesh.drawLines(canvas,paint);

        }
    }
...
}

    3. 關於算法:無論是漩渦扭曲動效,仍是仿造mac os 最小化效果。 原理都是一致的。惟一不一樣的地方在於算法。咱們須要分別設計算法來擬合出在目標時刻下新的頂點位置。

  • 漩渦動效算法:這裏須要用到極座標公式。夾角隨着時間增大而增大。半徑隨着時間增大而見小。而後在求出對應的x和y;
  • mac os 最小化:這裏我使用了2階貝塞爾曲線。
相關文章
相關標籤/搜索