現在說全景會不會有點遲=。=

UPDATE 2016.10.25

淘寶造物節用了一個引擎,另外原來造物節是 VML 出品的,今天才知道,和雙11的天貓漫遊頁面來自同一個工作室

哈哈哈,這個標題有點喪,因為最近的 TL 全是小程序,現在才想起來說已經503但是京東凹凸團隊模擬的淘寶造物節頁面是有點沒趕上時間,不過本來我就是個慢半拍嘛=。=

那麼我做了啥

先上一個簡單粗暴以天為被以地為床的 demo,全景的轉動全靠 CSS animation 實現:

只是靠著文末參考鏈接裡邊凹凸和 3D transform 的文章秒秒鐘實現出來的效果,這裡做一個小總結,順便記上當時看上面兩篇文章中思考了一會的地方,以便未來自己回頭查看,所以這篇(到目前為止)姑且算作一個讀書筆記。

三步走實現簡易全景

讓我們先約定或者是解釋一下術語

  • 場景:一整個頁面

  • 面片:組成場景的每一個相同大小的區域(其實應該也有大小不同的情況,只是我沒有想過要如何處理,所以現在我們只考慮區域一樣大的情形)

  • perspective:人眼離物體的距離,單位可以是 px、em 之類的

差不多了,那麼我們就來三步走吧~

  1. 確定場景中有幾個面片,用 rotate 和 translate 移動面片,組合出正多面體,此時構建出來的正多面體是這樣的(下圖來自Carousel 1,是一個正十一面體):

  2. 將「人眼」放入正多面體中(且先不調整 perspective),如果用上圖來比擬,面片 1 是肯定看不到了,因為已經在「人眼」的後面,相當於我們已經把自己置身於這個九面體中,但因為 perspective 還沒有做合理的調整,所以可能面片 9 和面片 2 依然可見

  3. 最後一步就是調整父級元素的 perspective,對,很蠢,我沒有找到能計算出最合理的值的公式,所以純靠手調 ORZ

這個三步走非常簡單,但是還遺留下了兩個問題:第一步中的「用 rotate 和 translate 移動面片」,具體的 rotate 和 translate 值要怎麼確定呢?。第二步中,如何將「人眼」放入正多面體中呢?

以簡單粗暴demo中的正八面體為例,一個個來。

第一步先為場景規劃一個大致的尺寸範圍,並設定 position:relative, 面片將相對於場景定位。

接著將所有面片確定好尺寸(這裡我們假設每個面片都是 200x200)以後,絕對定位。這時看到的頁面側視圖應該是這樣的,在還沒有旋轉移動過之前,所有的面片都是疊在一起,我們從瀏覽器窗口中只能看到未來的正八面體側面的最後一個面:

數學課之前先上一張來自凹凸團隊的圖,這張圖已經被我列印出來貼在辦公桌上了,真的好用:

正八面體的側面一共有六個面,所以面與面之間的夾角就是 60 度(360/6 = 60)。所以每個面片都要以 Y 軸為中心軸旋轉自身,第一個面旋轉 0 度,第二個面旋轉 60 度,第三個面就要旋轉 120 度……以此類推,直到第六個面旋轉 360 度。面片是旋轉好了角度,還要將面片延 Z 軸方向平移,只是有的向 Z 負軸有的向正軸,保證彼此相互接壤。平移的距離(設為 r)約等於 173px((200/2)/Math.tan(60/2*0.017453293))。

要實現正 X 面體,最好不要先平移再旋轉,因為元素的默認旋轉中心(transform-origin)都是自己的正中心點,如果先平移再旋轉,計算的公式會很複雜,遠不如先旋轉再平移來的方便。

所以最後這 6 個面的樣式代碼是這樣的:

.p-one {n background-color: #f0f;n transform: translateZ(-173px);n}n.p-two {n background-color: #000;n transform: rotateY(60deg) translateZ(-173px);n}n.p-three {n background-color: #e15;n transform: rotateY(120deg) translateZ(-173px);n}n.p-four {n background-color: #3fe;n transform: rotateY(180deg) translateZ(-173px);n}n.p-five {n background-color: #f0f;n transform: rotateY(240deg) translateZ(-173px);n}n.p-six {n background-color: #000;n transform: rotateY(300deg) translateZ(-173px);n}n

接下來要解決的問題是,怎麼把「人眼」放到正八面體中?這個問題很弔詭,它的主語是「人眼」,但是問題的答案卻是移動正八面體(突然想到了中學時候的有種類型題就是用逆向思維來解答,某種程度上也是個文字遊戲啊)。瀏覽器是不會渲染「人眼」背後的內容,也就是開發者不用對那部分內容做任何處理,它們根本不會被顯示出來。

「人眼」要置於正八面體之中,然後我們剛剛計算出來的正八面體正正相對的兩個面的距離是 346px (2*173),這個數值也是"人眼"可以移動的相對範圍。

不過還記得 perspective 嗎?我們一開始設定過一個「人眼」離正多面的距離(假設為 1000px),所以現在知道了 346px 還不夠,必須要知道正多面體的絕對位移範圍才行,範圍區間就是 (perspective-r, perspective+r),為什麼是 r 而不是 2r 呢?因為正多面體的其中一個面已經向 Z 正半軸方向移動了 r 的距離,所以這裡只需要加減 r 即可:

停留在 CSS Animation 轉換場景遠遠不夠

下面我要說的自己並沒有實現但想要做的內容,水先吹著:

  1. 可以加一個陀螺儀,用戶轉動自己的身體,看到更多的場景,套個 VR 眼鏡的殼子,好像可以做成偽 VR 呢

  2. 可以感受到一個 CSS 3D Panorama 的項目的 init 步驟是相同的,應該也能做成 boilerplate,但是全景的應用場景不多設計成本大:

    • 創建場景(初始化問題是:場景要由幾個面片來構成?)

    • 為場景的不同面片填充不同的背景圖

    • 每一個面片應該都能作為一個新的場景…只要硬體夠遞歸不是夢

最後感慨一下

明顯發現現在各種活動營銷頁面已經不夠看了,對我來說今年的營銷活動上,除了淘寶造物節(html5)和微信廣告(native)外,其他的 promotion 都是過眼雲煙,第二天就會連效果帶內容忘掉。

去年的營銷頁有印象的就是耐克的 3D 和吳亦凡(吳亦凡我也忘了具體 promotion 內容……),耐克的 3D 頁面似乎用了 three.js,我的小魅族都燒起來了。今年的造物節輕量了非常多,貌似用了個庫(然而我也不知是啥,等知道了再補上)。

微信廣告是 native 的,沉浸式和秒開的體驗非常棒(秒開是因為聰(wu)明(chi)地在 wifi 狀態下偷偷下載好了資源包,只是 16G 手機用戶還是有點生氣)。

不知道明年會是怎麼樣的形勢,特別現在小程序又出來了,產品的打法會更多,我就拭目以待準備好寫寫寫寫就好啦。

參考鏈接

  1. 覺得凹凸團隊很棒,要關注~ — CSS 3D Panorama - 淘寶造物節技術剖析

  2. 經典的講 3D transform 的一系列文章

  3. CSS 3D transform 的良心解讀 — CSS 3D應該注意的事項

推薦閱讀:

做了一個比較好玩的開源項目:前端全景渲染器 pano.gl
評測|Eyesir 4K+Mini:機內拼接有必要嗎?
評測|得圖F4四目全景相機: 出色同步+影像畫質,卻好用得不像專業級全景相機
VR視頻怎麼拍?你拍攝VR視頻遇到過哪些坑?
記錄整個空間——搭載 17 顆鏡頭的 Staro 能否秒殺魚眼全景相機?

TAG:CSS | 前端开发 | 360度全景 |