1. 程式人生 > >Android 立方體翻轉效果

Android 立方體翻轉效果

今天我們來看看如何實現一個立方體翻轉的效果,如圖

看上去很麻煩,實際上實現起來還是蠻輕鬆的。
這裡我們使用到的有兩個類。

  1. android.graphic.Camera 這是在影象學概念裡的攝像機,這是一個透視攝像機

  2. android.graphic.Matrix 矩陣,用來表示影象的變化。

頭疼的鑽研路開始

我們先從攝像頭上的角度分析:
正常情況下,我們是這麼看畫面的(那個電池一樣的東西就當是攝像頭吧)


我們要產生立方體的效果,那邏輯上應該是這麼看:

Camera提供了幾個介面,我們這使用到的介面有兩個:

  1. Rotate 旋轉

  2. Translate 平移

這兩個函式的操作都對畫布

的!
這裡我們首先要有2個View。xml結構入下:

<cn.geminiwen.canvassupport.view.SplashLayout
        android:text="@string/hello_world"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000" >
        <RelativeLayout
            android:layout_width
="match_parent" android:layout_height="match_parent" android:background="#f00">
</RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0f0"> </RelativeLayout
>
</cn.geminiwen.canvassupport.view.SplashLayout>

SplashLayout就是我的自定義佈局,用來繪製立方體效果的佈局。

我們把第一個view作為backgroundView,第二個View作為foregroundView,使得效果是從backgroundView翻轉到foregroundView

具體程式碼入下:

private void cube(Canvas canvas, double interpolation) {
        View foregroundView = getChildAt(0);
        View backgroundView = getChildAt(1);
        int width = getWidth();
        int height = getHeight();
        long drawingTime = getDrawingTime();
        float rotate;

        //begin drawForeground
        rotate = (float)(- sFinalDegree * interpolation);
        mCamera.save();
        mCamera.translate((float)(width - interpolation * width), 0, 0);
        mCamera.rotateY(rotate);
        mCamera.getMatrix(mMatrix);
        mCamera.restore();

        mMatrix.postTranslate(0, height / 2);
        mMatrix.preTranslate(-width, -height / 2);
        canvas.save();
        canvas.concat(mMatrix);
        drawChild(canvas, foregroundView, drawingTime);
        canvas.restore();
        //end drawForeground



        //draw Background
        rotate = (float)(sFinalDegree - sFinalDegree * interpolation);
        mCamera.save();
        mCamera.translate((float)(-width * interpolation), 0, 0);
        mCamera.rotateY(rotate);
        mCamera.getMatrix(mMatrix);
        mCamera.restore();

        mMatrix.postTranslate(width, height / 2);
        mMatrix.preTranslate(0, -height / 2);
        canvas.save();
        canvas.concat(mMatrix);
        drawChild(canvas, backgroundView, drawingTime);
        canvas.restore();
        //end draw Background

    }

這段程式碼放到ViewGroupdispatchDraw方法裡即可,因為ViewGroup只能在dispatchDraw方法中繪製子檢視。
其中,canvas代表畫布,interpolation代表動畫從0.0 到 1.0 的過程,方便插入器的使用。

這裡來解釋下我們的過程。

View狀態變換

起始狀態background是這樣的:

  1. 繞Y軸正方向轉90度

  2. 畫布x軸移動到width的位置。

可以參照上圖中的畫布2的狀態。

終點狀態是這樣:

  1. 繞Y軸正方向0度。

  2. 畫布x軸移動到0的位置。

可以參考上圖中的畫布的狀態。

旋轉問題

綜上所述,我們設定轉動角度sFinalDegree為90。
interpolation從0到1的過程,
background的rotate就變成了從900的過程。

平移問題

這時候我們考慮平移的情況,這個情況會比較複雜,因為我們這裡有兩種平移方式,平移攝像機或者直接平移畫布

這裡我們說下區別,如果移動攝像機,會導致影象的投影發生變化,舉個例子:
比如我們已經在投影上繞Y軸旋轉90度,如果移動X軸的話,看如下圖的區別:

1、未平移攝像機

2、平移攝像機


從圖上我們知道,這個旋轉過的畫布的前端和後端我們都是可以看見的,這當然不符合我們要求,那麼我們直接平移畫布是什麼意思呢?

我們知道對攝像機做了操作之後,應用到畫布上,實際是畫一個畫布的投影,直接移動畫布的話,就是改變其座標系系統,達到效果,我們可以理解為同時對攝像機和view進行平移,最終達到的效果就是攝像頭相對view的位置和1一樣,但是我們的畫布卻平移了,這就達到了我們最終的要求。

我們看程式碼雖然我們平移的是畫布,但是我們平移的過程中確是使用移動攝像機的方式來繪製投影,這又是為什麼呢?

我們從三角函式的投影來解釋這個問題。
首先看見我平移攝像頭的方式是線性的,也就是y=kt這種方式,斜率一定,也就是隨著時間變化,我平移的距離是線性增加的。那麼考慮旋轉的時候的投影情況:
被旋轉的角就是角a,我們的畫布長為width,那麼畫布的投影長度為 
width * cos(a)

它是一個三角函式。變化趨勢先快後慢,因此我們在旋轉過程中會看見右邊露出背景,造成視覺上的不友好,怎麼解決這個問題呢? 

這時候就藉助我們的攝像機平移的投影方式。

這裡綠色的線是我們的投影線,它的投影長度比cos(a) * width要長很多,因此它就可以讓我們在旋轉過程中不產生黑邊,給人視覺上的飽滿感,會讓我們的視覺效果好很多。

我們的foregroundView就是一個backgroundView的逆向過程,因此使用類似的程式碼,然後假設interpolation是從1-0的過程即可,同時它的座標系整體要往左移動一個螢幕。

總結

做UI的效果,特別需要一些比較好的資料基礎,在影象處理中,搞清楚透視、矩陣的一些計算方式和概念非常重要,今天我們介紹了利用Camera來進行輔助我們進行矩陣的計算。

原始碼


相關推薦

Android 立方體翻轉效果

今天我們來看看如何實現一個立方體翻轉的效果,如圖 看上去很麻煩,實際上實現起來還是蠻輕鬆的。 這裡我們使用到的有兩個類。 android.graphic.Camera 這是在影象學概念裡的攝像機,這是一個透視攝像機。 android.graphic.Matrix

Android 動畫分析之翻轉效果

大家一定看到過三維的翻轉效果,所以今天在這裡簡單的給大家分析一下,我們怎麼樣才能實現Android中的翻轉動畫效果的實現,首先看一下執行效果如下圖所示。 效果圖: Android中並沒有提供直接做3D翻轉的動畫,所以關於3D翻轉的動畫效果需要我們自己實現,那麼我們首先

HTML5+CSS3立方體3D翻轉效果

1、呼叫CSS樣式: <link rel="stylesheet" type="text/css" href="css/style.css" /> 2、呼叫JS外掛程式碼: <script src="js/prefixfree.min.js"></script> 3、新增

Android頁面翻轉動畫(模仿CSDN賬號登入的翻轉效果

昨天下載了CSDN的APP,進入多種方式選擇登入的頁面,然後我選擇用CSDN賬號登入,發現有頁面翻轉的效果進入登入頁面。瞬時感覺好炫,自己感覺效果很好。平時別的APP登入的時候,就是直接進入登入頁面,沒有任何效果。這次看到旋轉的效果,頓時眼前一亮,所以我就研究了一下,想做個

android 翻轉效果動畫原始碼

     最近專案上要求做一個翻轉的動畫效果,由於動畫還沒有怎麼使用過。然後再網上找到一份很實用的翻轉動畫先用起來,以後再學習下動畫相關的。 原始碼修改後如下: public class Fl

Android Vibrator震動效果

can cnblogs () 否則 指定 pan log 需要 動效 android震動器:Vibrator Android手機中的震動由Vibrator實現。 Vibrator vibrator = (Vibrator) getSystemService(VIBRATO

Android 仿 窗簾效果 和 登錄界面拖動效果 (Scroller類的應用) 附 2個DEMO及源代碼

@override 宋體 off down != 過程 事件 學習 border 在android學習中,動作交互是軟件中重要的一部分。當中的Scroller就是提供了拖動效果的類,在網上。比方說一些Launcher實現滑屏都能夠通過這個類去實現。以下要說的

Qml翻轉效果

vra code pretty class chan examples 狀態改變 gif avr 使用Flipable, 根據狀態改變進行翻轉動畫 Flipable{ id: flip width: 300 heig

android 水波紋效果實現

drawable color utf true odi lec .com enc orm 1.在drawable文件下,新建seletor,作為button的背景,這裏我用的是兩個圓角的shape <?xml version="1.0" encoding="utf-

Android時間軸效果,直接使用在你的項目中

Coding return pro 查詢 gpo ava person turn rst 近期開發app搞到歷史查詢,受騰訊qq的啟示,搞一個具有時間軸效果的ui

圖片點擊翻轉效果

com cli ive frame 註意事項 from UNC orm ase 此處寫法是 css===寫好樣式放在一個新class名 1 @keyframes flipping{ 2 from{transform:rotateY(0);} 3 to{tr

flip 翻轉效果 css3實現

分享圖片 參數 back res absolute font name position serve 1.實現代碼 <!DOCTYPE html> <html lang="zh"> <head> &

Android點陣屏效果的控制元件

最近發現了一個比較好玩的效果,android實現的LED點陣螢幕效果,挺有意思的,於是花了點時間實現了一下,這個用在演唱會上的粉絲當成牌子舉是不是挺好的呢,或者是送給妹子?哈哈~ 實現思路比較簡單,主要是計算漢字對應的點陣矩陣,漢字通過GB2312編碼,每個漢字對用兩個byte來表示,而一個漢字

Android懸浮窗效果的實現

具體懸浮窗效果實現參考大神部落格:http://blog.csdn.net/stevenhu_223/article/details/8504058 至於在拖動懸浮窗時會產生抖動,這是因為OnTouch事件中呼叫錯了函式,在網上查了下,弄明白這兩個函式的區別: event.getX()

Android刮彩票效果

實現分析: 1.底部一張圖片 2.圖片頭部是一個矩形遮擋圖片 3.通過滑動監聽,讓矩形缺失,露出底部圖片 主要程式碼如下: private RectF rectf; private Bitmap bitmap = BitmapFactory.de

Android 水波紋效果

今天翻看部落格,發現了水波紋效果。順便研究了一下 一,Touch Feedback(觸控反饋)  1,原始自帶效果 程式碼: <Button android:layout_width="wrap_content" an

移動開發----Android模仿打字機效果的自定義View實現

前言   在做splash介面的時候,需要做類似於打字機打字的效果,字一個一個地蹦出來,顯示每一個字都帶有打字的聲音。 效果演示 實現原理:   這個其實不難實現,通過一個定時器不斷呼叫TextView的setText就行了,在setTex

Android點贊效果的實現

先看下點讚的效果圖 首先新增依賴 api 'com.sackcentury:shinebutton:0.2.0' xml佈局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=

Android DrawerLayout抽屜效果和Toolbar標題欄的簡單使用

話不多說先看執行效果: View層 佈局layout: activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayou

Css圖片的翻轉效果

效果圖: 程式碼: .turn{ -moz-transform: scaleX(-1); -o-transform: scaleX(-1); -webkit-transform: scaleX(-1); -ms-transform: scale