Android 介面漩渦扭曲動效實現
阿新 • • 發佈:2018-12-03
背景:之前偶然看到優酷有類似的頁面切換動畫效果。於是自己也打算來實現下這樣的效果。
動效說明:點選介面中的任意位置,介面以點選位置作為中心點,開始以漩渦狀態,扭曲,收縮。直到消失。
直接上我實現的效果:
一,方法原理說明:
- 將頁面生成bitmap。
- 使用自定義View來繪製扭曲的影象。 影象繪製的時候使用的關鍵的api 是: canvas.drawBitmapMesh();
二,實現細節說明:
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 中,對圖片進行畫素級別的修改。 雖然成功了,但是效率卻很慢。)
關於API drawBitmapMesh 可以參考一下這篇博文:使用drawBitmapMesh方法產生水波
期原理猜測應該是使用了opengl 中紋理,座標變換對映的技術。(只是猜測)
drawBitmapMesh使用方法:將原始圖片分割成為M行,N列。 並計算得出原始的每個交點再二維空間內的座標。 坐上角為(0,0)點。 水平向右為X正方向。 垂直向下為Y正方向。 使用漩渦演算法,計算每一幀下,原始頂點(線的交點)在當前時刻下的座標位置。即生成的區域性變數ve[]; 這樣介面就能顯示出影象被扭曲的動畫。
當然:分割的行列越多,效果就會越好。
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階貝塞爾曲線。