如何基於Weex實現創新交互體驗?手淘開源技術BindingX案例解析
阿里妹導讀:隨著手淘流量紅利時代的結束,如何通過精細化運營、不斷提升App用戶體驗,成了我們新的目標。手淘技術團隊童鞋在有限的條件下,巧妙利用Weex,實現了以往用純native才能實現的卡片式交互形態,給用戶創造了小驚喜(該技術已開源)。下面讓我們一起來深入了解。
文章一開始,我們先來看兩張效果圖:
大家第一眼看到,是不是覺得這兩個產品應該是純native實現的,weex貌似不具備這個能力。但實際情況是:這是依賴weex容器純js實現的功能,它並沒有依賴native來實現這些UI組件(如slider)。那大家可能就很好奇了,這酷炫的交互體驗到底是怎麼實現的呢?我就拿「每日好店」(手機淘寶首頁的主打欄目之一)的卡片交互來解析下。
背景
隨著手淘流量紅利時代的結束,如何經營好現有的客戶成了重中之重,導購線也針對這一情況,從以前的CTR、GMV導向,慢慢轉向精細化運營,致力於提升用戶體驗,從而提升在線時長、滲透率。在此背景下,「每日好店」產品的升級改造勢在必行。經PD和交互設計師的努力,便產生了新的卡片式交互的產品形態。
產品功能拆解
剛開始拿到的交互稿是這樣:
拿到交互稿,首先進行的是產品功能的分析和拆解。整個產品可以拆解成以下幾個功能部分:
- 卡片的橫滑並且在橫滑時有縮放
- 視頻卡片上滑放大,及點擊向下按鈕時縮小
- 頁面背景為當前卡片的封面圖,隨著卡片的滑動而變化
- 卡片導航數字隨著卡片的滑動而變化
- 頁面需要佔滿全屏,不能有系統默認的導航條
- 卡片需要有圓角和陰影
- 視頻未播放時,封面需要有呼吸的效果
實現過程
當功能拆解後,便是研究實現方案了。要實現這些功能,我們有兩條路可以選:一條是走native,由native來實現這些功能,另一條是通過js基於weex容器來實現。當然,首先想到的是native實現,因為直接使用native來實現,體驗肯定是最優的,而且weex已有的能力貌似還沒法實現這些功能。但是native實現的話,除了能保證產品的體驗之外,也存在它的弊端:
1、代碼不可複製,往往是一次性的產物
2、需要Android、iOS至少兩個人開發,比較耗人力
3、發版麻煩,得跟著手淘的發版節奏走,很難進行靈活的產品迭代
所以從長遠的角度來看,我們更希望使用weex來實現既帶有native的體驗、又能靈活發布快速迭代,還能一個前端搞定多端的目標。
接下來,驗證weex的能力是首先要做的事情。我們先寫了兩個demo,一個demo使用了weex的animation module來實現視頻卡片放大全屏和縮小的功能;另一個demo使用了weex提供的touch事件,用在web時代純前端的方式來實現了卡片橫滑的功能。通過demo驗證,發現weex端最主要存在的問題是使用touch事件時的性能問題,在iOS端,卡片滑動的性能還可以接受,但是Android端則非常卡。究其原因,因為每次touchmove觸發的時候都有native到js之間的一次通信,而每次move事件結束的時候我們都要修改位置,又有js到native的一次通信,通知native重新渲染,而touchmove的觸發頻率又是相當恐怖的,這樣頻繁的diff計算及通信就耗費了大量的資源,導致頁面卡頓。
基於這一點,我們設計了BindingX的方案。每次只要在touchstart的時候,js接受native的事件,然後將move時用到的計算表達式傳遞給native,move的操作全部由native端來做,完全省去了diff計算及native跟js之間call的消耗。
當然除了這個問題外,也還存在其它的一些問題,最終我們理出了需要實現好店功能weex缺失的所有能力,並推動weex全部實現了這些能力。
以下列出了針對好店這次weex新增的能力:
1. BindingX: 手勢操作大飛躍,想怎麼變就怎麼變
正如上面描述的,它主要是為了解決weex暴露的touchmove的性能問題,每次只要在touchstart的時候,js接受native的事件,然後將move時用到的計算表達式傳遞給native,move的操作全部由native端來做,完全省去了native跟js之間call的消耗。而且BindingX可以同時進行多個元素的綁定,即你移動一個目標元素的時候,可以同時移動多個其他關聯元素。語言上描述起來有點晦澀,用偽代碼描述下好店卡片橫滑時背景漸變、卡片縮放、數字翻滾的功能可能更加直觀:
從偽代碼可以看出,這個使用過程其實是非常簡單的:
1、給目標元素綁定pan事件
2、創建目標元素和關聯元素的表達式綁定關係
BindingX的能力,其實給了前端很大的發揮空間,我們完全可以像以前在web端開發UI組件一樣,自己來開發一個weex的UI組件(如slider組件),甚至打造一個帶有強交互能力的UI組件庫。
2. NavBar Transparent:導航欄透明了,設計師又多了更多的創造空間。
導航欄透明的使用非常簡單,你只要在url後面加個wx_navbar_transparent=true,導航欄就神奇地變透明了(以前pd、視覺、交互提的效果終於可以實現了)。 除了透明之外,它還有個隱藏導航欄的功能,只要在url後面加個wx_navbar_hidden=true,就能把導航欄隱藏了,我們就完全可以自己來控制頁面的導航樣式及跳轉邏輯了。
3. NavBar Button Color: 後退鍵也能變顏色。
這個功能其實跟導航欄透明是配合使用的,當導航欄透明之後,導航欄的背景色就變成了頁面的背景色了,而具備了這個能力後,設計師就完全可以根據頁面背景色的不同,來調整導航欄上按鈕的顏色了。 當然它的使用方式也很簡單:
4. 陰影:卡片效果更突出,立體感撲面而來。
以前當視覺提出陰影的效果,是不是會很尷尬,要麼說weex不支持,要麼可能得用很geek(通過圖片)的方式才能實現。現在weex陰影的功能終於有了落地,不過很遺憾android並沒有實現w3c box-shadow的效果,它只提供了elevation的參數,來實現box-shadow第三個參數的效果。
5. 圓角:連視頻組件也能支持圓角了,卡片效果更出眾。
以前在Android端,要實現圓角,必須在裡層的元素中使用border-radius來控制圓角,因為它的border-radius屬性是每個基礎組件自己實現的(如view,image)。這樣你在外層的view中添加border-radius是完全不起作用的,使用起來相當不方便,而視頻組件根本就不支持border-radius屬性。而現在能力增強之後,你只要在想要圓角效果的最外層加上border-radius就可以實現圓角的功能,即使裡面是視頻,也可以圓角顯示。這背後,其實是border-radius的實現原理髮生了改變,以前是每個基礎組件自己實現,現在是放到渲染層來做。
當然在iOS端本來就支持得不錯,只是你在最外層除了border-radius外,還得加個overflow:hidden的屬性。
6. Scrollable:我讓你動,你才能動。
scroller組件新增了一個scrollable屬性,讓我們可以靈活來控制scroller是否可以滾動。
7. Blur:毛玻璃效果從此就是一個屬性的事。
圖片想實現毛玻璃的效果只要在樣式中增加filter屬性即可。
只是現在filter的值,在Android和iOS的模糊力度不太一樣,這個功能可能需要再改進下。
8. 回退按鈕事件攔截:讓業務自己來控制回退邏輯
當weex容器還沒有實現hash之類的單頁處理的基礎能力時,回退按鈕事情攔截的功能,其實為我們提供了變相實現單頁的能力。頁面的history,完全自己來維護,通過回退事件的攔截,來控制pop history的邏輯。當然這只是過渡方案,要靈活地實現真正的單頁應用,還是需要weex實現w3c標準的hash之類的API。
以上就是這次好店產品交互升級,push weex端新增的能力。
當然除了這些新的能力,我們也靈活使用animation module,來配合BindingX處理手指釋放之後的一些動畫效果,及視頻卡片放大縮小的效果。從總體效果來看,已經基本達到了設計師想要的樣子。
開源
目前,我們已將BindingX技術開源,希望幫助更多開發者解決相似問題。
BindingX 是針對weex和React Native上富交互問題的一種解決方案。它提供了一種稱之為 "Expression Binding" 的機制,可以在 weex、React Native 上讓手勢等複雜交互操作以60fps的幀率流暢執行,而不會導致卡頓,因而帶來了更優秀的用戶體驗。
BindingX 通過插件的形式同時支持React Native和weex。在weex上,可以作為一個 weex 模塊直接註冊到weex環境中, 在 JS 層同時支持 weex DSL 和 Rax DSL 。在 React Native 上,也可以以類似的方式使用。
開源地址:
https://alibaba.github.io/bindingx/guide/cn_introduce
推薦閱讀:
※絕地求生外掛,那麼你認為源代碼開源是怎樣的?
※Android面試課程總結一(開源框架)
※全面應用 linux並棄用windows的經驗分享