自如客APP裸眼3D效果的實現

語言: CN / TW / HK

我的影片 1.2021-07-26 19_41_36.gif

背景

移動端介面設計如此火熱的今天,各類大廠的設計規範和設計語言已經非常的成熟,我們想做一些在這套成熟的設計規範之外的嘗試和創新,所以有別於傳統的banner互動形式成為了我們的發力點。

設計理念

由於app版面空間有限,除了功能導向、閱讀習慣和設計美觀外,自如想在既定的框下,做一下不同的設計嘗試,哪怕這種嘗試只能提升使用者1%的觀感。可能租了幾年自如的房子,用了幾年自如客app,你可能也不會注意到一些小的細節。但如果哪天,作為使用者的你突然發現了這個隱藏的“彩蛋”,看到了自如在這些小細節上的用心,我相信那天你將會對自如這個品牌有更深層次的認識和理解。

裸眼3D技術一般都是應用在裸眼3D大屏、全息投影等等比較常見的場景中,在APP的banner上應用,的確也是一次全新的嘗試。我們通過藉助移動裝置上的感測器、以及自身的屏顯清晰度、畫面呈現,將2D影像轉化為景深效果,以呈現出不用"3D"眼鏡就可看到的3D效果。

實現方式

以下以Android為例,介紹一下該效果的實現方式。

分層

自如客app的banner其實一直在創新當中,有專門注意過的同學可能知道,在裸眼3D效果之前,自如客app其實就已經實現了分層,當時為了實現更加自然和精緻的切換效果:在每個banner滑入滑出的時候,底部其實會在原地進行漸顯漸隱,內容會跟隨手勢滑入滑出。此次為了實現3D效果,我們在以前分層的基礎上加了一層中景,將原有的前景拆分為前景和中景。

image.png

上圖的sl_bg為背景,pv_middle為中景,sl為前景

由於切換的互動,實際上banner使用了兩個viewpager進行了聯動。背景在最底層的viewpager裡面,中景和前景在另外一個viewpager裡。

跟手位移

開啟自如客app後,使用者操作裝置可以明顯感受到畫面的錯位移動,造成視覺上的景深效果。這種錯位移動其實就是藉助裝置本身的感測器來實現的,具體實現方式是我們讓中景始終保持不動,同時從裝置感測器獲取當前裝置對應的傾斜角,根據傾斜角計算出背景和前景的移動距離,然後執行背景和前景移動的動作。如下圖所示:

image.png

為了使用的方便,我們封裝了一個SensorLayout,專門用於根據裝置的傾斜角執行內容的位移; SensorLayout內部的主要實現:

註冊對應的感測器

```java mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); // 重力感測器 mAcceleSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // 地磁場感測器 mMagneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

mSensorManager.registerListener(this, mAcceleSensor, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mMagneticSensor, SensorManager.SENSOR_DELAY_GAME); ```

計算偏轉角度

```java if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { mAcceleValues = event.values; } if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { mMageneticValues = event.values; }

float[] values = new float[3]; float[] R = new float[9]; SensorManager.getRotationMatrix(R, null, mAcceleValues, mMageneticValues); SensorManager.getOrientation(R, values); // x軸的偏轉角度 values[1] = (float) Math.toDegrees(values[1]); // y軸的偏轉角度 values[2] = (float) Math.toDegrees(values[2]);

``` 通過重力感測器和地磁場感測器,獲取裝置的偏轉角度

根據偏轉角度執行滑動

java if (mDegreeY <= 0 && mDegreeY > mDegreeYMin) { hasChangeX = true; scrollX = (int) (mDegreeY / Math.abs(mDegreeYMin) * mXMoveDistance*mDirection); } else if (mDegreeY > 0 && mDegreeY < mDegreeYMax) { hasChangeX = true; scrollX = (int) (mDegreeY / Math.abs(mDegreeYMax) * mXMoveDistance*mDirection); } if (mDegreeX <= 0 && mDegreeX > mDegreeXMin) { hasChangeY = true; scrollY = (int) (mDegreeX / Math.abs(mDegreeXMin) * mYMoveDistance*mDirection); } else if (mDegreeX > 0 && mDegreeX < mDegreeXMax) { hasChangeY = true; scrollY = (int) (mDegreeX / Math.abs(mDegreeXMax) * mYMoveDistance*mDirection); } smoothScrollTo(hasChangeX ? scrollX : mScroller.getFinalX(), hasChangeY ? scrollY : mScroller.getFinalY()); mDegreeX即為第二部中獲取的偏轉角度,mDegreeXMin和mDegreeXMax為X軸可發生偏轉位移的角度最大值和最小值,mYMoveDistance即為Y軸上的最大偏移距離(圍繞X軸發生旋轉,檢視會沿Y軸上發生位移);Y軸上的偏轉同理;就算好X軸和Y軸的偏移距離後,使用scroller進行滑動;

實現總結

讀到這裡,相信大家已經基本瞭解了這套banner的實現方案。Android端在佈局上進行了分層,中景位置不變,藉助重力感測器和地磁場感測器獲取偏轉角度,根據角度使背景和前景進行錯位移動。iOS端的實現原理也基本一致,不再贅述。

本文作者:自如大前端研發中心-黃進

招聘資訊

自如大前端研發中心招募新同學!

FE/IOS/Android工程師看過來

公司福利有: - 全額五險一金,並額外購買商業保險 - 免費健身房+年度體檢 - 公司附近租房9折優惠 - 每年2次晉升機會 辦公地點:北京酒仙橋普天實業科技園 歡迎對技術有執著熱愛的你加入我們!簡歷請投遞 [email protected]