【轉】跨終端實踐-天貓試戴的解決方案

天貓

原文 https://github.com/tmallfe/tmallfe.github.io/issues/4javascript

體驗完產品,具體講下技術實現方案,總體的實現過程能夠分爲:html

拍照->得到圖片數據->將商品與圖片合成->生成效果圖->用戶保存圖片html5

拍照

跨終端調取攝像頭java

這是試戴的關鍵一步,考慮到須要支持到各個終端,因此優先想到使用標準的web方案來實現:WebRTC - getUserMediajquery

基於 getUserMedia,面向 mobile 快速嘗試,基本完成了主要的功能android

但 getUserMedia 的支持狀況並不理想,尤爲是 sarfari 的不支持讓廣大 ios/mac 用戶沒法體驗,這裏就須要 PC、mobile 的兼容處理,以跨終端 mobile first優雅退化的思路設計兼容API:ios

  1. 在瀏覽器中若是沒法支持,將採用 flash 方案補齊
  2. 在 native 中,優先採用 native api 補齊

camera

控制先後攝像頭(web)git

對於戒指的試戴,手機上咱們指望優先調用後置攝像頭,在 web 中啓動時就須要設置優前後置攝像頭,W3C 文檔還處於 Draft 階段,相對還不是特別完善,能夠經過以下設置:github

{
    video:{
        optional: [
            {
                sourceId: $sourceId
            }
        ]
    }
}

經過 MediaStreamTrack.getSources 可得到設備的全部 sourceId,注意:考慮設備可能沒有外設如臺式機或外設設備不可用(在虛擬機或遠程),這種狀況下會報錯,因此須要 try&catach 容錯。web

控制拍照時圖片尺寸(web)

不一樣的終端,攝像頭拍攝的圖片照片尺寸是不一樣的,若是咱們只須要得到某一部分圖像,就須要對圖像作剪裁,在 WEB 中爲了避免引發用戶疑惑,展示給用戶拍照界面時,所見最好就是所須要的部分

舉個栗子:咱們指望得到一個正方形的圖片,可是 rmbp 中攝像原始是 16:9 的圖像,考慮方案有:

  1. 考慮設置 video 的 width/height 讓圖像自動充滿 video(參考官方文檔並無規定這部分實現,最新草案也無方向,這個方案走不通)
  2. 將 video 部分隱藏,知道目前圖像的原始尺寸,而後垂直居中,方式如圖:

img-size

須要注意的是:video API 中有 videoHeight 及 videoWidth 兩個屬性,當 video play 時理論這兩個屬性就是當前圖像的寬高,但實際狀況 Mozilla 存在一個 bug#926753,play 時仍沒法準確獲取,兼容的方案輪訓監聽:

Event.on(video,"play",function(){
    if(this.videoHeight===0){
        return S.later(arguments.callee,100,false,this);
    }
    // now width/height ok
}

獲取數據: 在傳輸大數據狀況下的web與native通信

在拍照完成 native 中須要把圖片數據傳遞給 web,另外用戶保存圖片到本地時,web 又須要把合成好的圖片數據傳遞給 native 讓其保存,這邊涉及 native 與 web 的傳遞大數據通信:

  1. native -> web:

    1. android:可經過 WebView#addJavascriptInterface() 向 web 注入 js 方法
    2. ios:可經過 UIWebView#stringByEvaluatingJavaScriptFromString() 執行 js 函數,兩種方式向 web 傳遞大數據都沒有問題
  2. web -> native:

    1. android:因爲能夠把 native 類暴露給 web,js 能夠調用暴露的方法和 native 通信,大數據也沒問題;
    2. ios:因爲是採用 UIWebViewDelegate 方式,監控 request 方式通訊,js 經過自定義協議的 URL 用 iframe 請求,傳輸大量數據時便存在問題;解決這個問題方案:既然 native 能夠和 web 順暢通訊,就能夠通知 native 一個 js 函數名,讓 native 本身來取。

getdata

合成展示:定位戒指位置

比較簡單,用圖片說明: picWidth/maskWidth = x1/x = w1/w

picshow

生成圖片:Canvas 圖片跨域

知道了具體位置,生成圖片即可以簡單的調用 canvas.toDataURL 得到圖片數據,但這裏涉及一個圖片跨域問題:
Canvas 獲取圖片數據會有跨域的限制,以前有:imageProxy flash來作代理的方案,可是這個方案仍然不夠高效和簡潔,尤爲是對於 mobile 更無能爲力

最好的方案是 web 標準的 CORS,經過讓服務器返回 allow-origin 的 header,讓 canvas 能夠正常處理:

// http response header: Access-Control-Allow-Origin: *

img.crossOrigin = "Anonymous";
img.onload = function() { 
    ctx.drawImage( img, 0, 0 );
    canvas.toDataURL("image/png");
}

組件化 & Mobile First

在整個開發的過程當中是以組件化的思路分層處理,並封裝成了具體的組件,經過封裝的組件,後續拍照、試戴能夠快速搭建完成,除了天貓自身業務特點的組件外,比較通用的有:

  1. camera 組件:底層跨終端拍照組件,後續會移植到阿里 HybirdAPI 一部分
  2. try 組件:上層的試戴組件,處理圖片位置、合併、移動旋轉等,可配置不一樣模板及參數快速支持其餘類型試戴(如眼鏡)

再設計跨終端有組件時,經驗是優先面向 mobile 設計,這樣邏輯及交互流程更加簡潔,可讓 API 涉及更加清晰,後續正對 PC 適當兼容。

聊業務

最後簡單聊下這個業務:這是一個技術驅動業務的項目,從初期的業務重點在頻道,中間經歷幾回業務調整,到目前把試戴做爲業務後續的重點,能夠說這個產品在其中起到了不少的做用,其中幾點經驗:

  1. 不只本身看到價值,重要讓合做夥伴也看到價值

    1. 在資源有限的狀況下,做爲技術人員去影響業務策略是不易的,認同事情的價值是關鍵一步
  2. 快速的產出 demo,驗證可行性及讓合做夥伴瞭解成本及效果

    1. 有時不是業務看不到方向而是擔憂成本,這是技術的優點,但須要作出來看

後續

後續試戴還有不少地方能夠發力,比較重要的一些方向:

  1. 支持更多品類:項鍊、眼鏡、耳環、手鐲、手錶等其餘類目
  2. 能夠考慮結合圖像搜索作相關推薦
  3. 嘗試使用圖像識別,減小已有模板對比的成本,example

  1. html5 vedio 簡介
  2. Capturing Audio & Video in HTML5
  3. getUserMedia 兼容性
  4. tainted canvas
  5. html5 video face detection
  6. html5 膚色檢測
相關文章
相關標籤/搜索