在七牛雲校園黑客馬拉松中,一款設計優秀、邏輯清晰的白板作品脫穎而出,獲得第二名的好成績,這就是來自鄭州大學Since團隊的White Rose白板,以下是他們的設計和架構分享。 一、前言 White Rose是參加七牛雲hackathon比賽的作品,賽題的主要內容是開發一個「多人協作白板」,旨在鼓勵 ...
在七牛雲校園黑客馬拉松中,一款設計優秀、邏輯清晰的白板作品脫穎而出,獲得第二名的好成績,這就是來自鄭州大學Since團隊的White Rose白板,以下是他們的設計和架構分享。
一、前言
White Rose是參加七牛雲hackathon比賽的作品,賽題的主要內容是開發一個「多人協作白板」,旨在鼓勵在校大學生用編程創造價值。
賽題核心需求包含三個:
- 多人可以加入一個房間,同時進行繪畫(儘可能多的形狀隨意繪製)
- 所有操作可以撤銷和恢復
- 可以創建不同頁面,支持只讀模式(頁面鎖定後,所有人不可編輯)
二、產品設計
(1)願景
基於hackathon的比賽要求,我調研了一些白板軟體,這些軟體不乏有一些「操作困難」「功能繁雜」等問題。所以,我定下一個產品願景:「做一款從兩歲到八十歲都能用的白板」
(2)追求
基於以上願景我也設立了幾條產品追求:「功能一鍵即達」「界面極致簡潔」「內容高度自由」
作為喬布斯的粉絲,印象中喬布斯當年設計iphone時,要求工程師所有的功能操作不能超過3步,而對於白板一個單獨的軟體來說「進入」一步,「功能選擇」一步,所以留給我的只有一步了。
(3)界面
為了讓界面足夠簡潔,我將所有「擴展」功能全部放到了「上下左右」四個隱藏菜單里,從而讓整個頁面除了四個「必要數據」外,就只有一塊“純粹的白板”。
- 對於兩歲的小朋友來說進入就可以直接隨意的塗鴉。
- 對於八十歲老教授來說,這用起來跟教室的黑板一樣。
下麵分別是整體的界面效果。
無論多大的屏幕,什麼形狀的屏幕,都會無失真的自動擴張,因為它本質是一個高寬100%的矢量圖。
因為不同屏幕的大小限制,這樣的設計可能回導致小屏幕的人看到的內容沒有大屏幕的「完整」。
對於有些軟體的處理可能會有利用「拖拽頁面」功能來確保每個人所能接收到的數據一致,這將意味著,用戶的每次觸屏操作,軟體都要區分用戶是想「拖拽頁面」還是想「繪畫」,而用戶也需要在兩個功能間頻繁切換。
而我的理解:“白板”本質是一個大號的草稿紙,當我們給一群人講一些內容的時候,「演講者」可能隨手會在白板上寫下他講的關鍵詞「power point」,一般作為「演講者」會寫在一個大家都能看到的地方,這對「演講者」不會增加太大負擔,而對於「聽眾」一邊聽內容,還要一邊還要拖拽頁面去確認演講者寫在那裡,這個負擔更大。
回想一下我們在教室上課的時候,老師會儘量把內容寫在中間靠上的位置,而不是底部,因為前排同學會擋到內容。
所以我摒棄了「拖拽頁面」的功能。
當然「縮放」也不乏是另外一種解決方案,但是也會徒增操作者(縮放)的使用負擔,並且還會引入另外一個問題就是「失真」。
關於顏色:
其實在選擇白板的底色的時候,可能就是一個白色,但是其實白色也是五彩斑斕的,該用什麼呢?
我想到一個詞「青紅皂白」,索性我就用「青紅」和「皂白」調製了一個對眼睛更加柔和的 「青紅皂白色」作為白板的底色。
(4)拓展功能
設計好了整個頁面,接下來就是功能設計,我在設計界面的時候,預留了4個隱藏菜單欄來放拓展白板功能,為了讓所有功能「一鍵即達」,並且更簡單的使用,我採用了icon + 文字描述的方式,讓用戶更易理解。
整體展開如下圖所示:
為什麼是這樣的擺放呢?
1、功能分類
根據賽題要求的功能,我將所有功能分為了四類。
- 形狀拓展:用戶可以選擇圓、長方形、菱形、三角形、直線等形狀。
- 顏色拓展:用戶可以修改所有形狀軌跡的顏色。
- 大小拓展:圖形的大小和線條的粗細可以切換。
- 頁面拓展:頁面可以添加刪除和切換,另外頁面的內容支持撤銷和恢復。
2、何處安放
我在想這個問題的時候,想象了在一張紙上作畫的場景。
- 一般我們習慣在桌子右側放上各式各樣的水彩筆,方便我們切換顏色,所以我將「顏色拓展」放在了右側。
- 我們習慣在桌子的上方和左側放尺子、圓規之類的用來拓展圖形和豐富繪畫形狀的工具,所以我將「形狀拓展」「大小拓展」放在了左側和上側。
- 當我們要做翻書、撕頁等頁面操作時,一般會從右下角開始,所以我將所有的「頁面拓展」放置到了下側,同時右下角有一個對應頁面的頁碼,也因為大多數書的頁碼在這個位置。
(5)自由佈局
上面講到,我根據我個人的想法將各個功能進行了分類,並且按照我所理解的「更方便的佈局」進行了排放,但在實際操作過程可能並不符合一些其他用戶的操作習慣,比如:左撇子。
因此我將每個功能做了集成,並且可以隨意的改變不同功能所在的位置,也就是所有的功能佈局,用戶可以根據自己的想法進行佈局上的DIY。
三、架構設計
因為本次開發的周期只有21天,另外工作日的白天還需要上班,非常緊迫。所以需要採用非常簡單且高效的架構設計,當然也需要考慮一些後續擴展的可能。
(1)整體架構
為了更好的「持續集成」我們採用自建的gitlab管理代理,並使用gitlab-runner完成自動化部署。
整體架構圖如下圖所示:
(2)交互模型
對於後端來說,為了更加高效的溝通,我將整個交互模型,定義為一個群聊,群內所有人的消息統一發給服務端,然後服務端再統一轉發給其他人。
後端只需要確認三點:1.誰發的消息。2.發到那個群里的。3.消息類型。
整體交互結構如下:
{
"type": 1234, // 操作類型
"fromId": 123, // 發送人id
"roomId": 1234,// 所在房間
"time": 152150025421564 //時間戳,前端不需要發送
"data": {} // 操作內容
}
這樣做的兩個好處:
- 所有消息有一個統一的時序(即服務端時間)
- 後端完全無需關註「data」的具體內容。只根據type區分「接收」「分發」「存儲」操作。
(3)data模型
data模型主要是前端所發送的和接收到的message里的data結構。
data裡面該放什麼?我將用戶的所有操作定義為option,將用戶的所有option放到data裡面完成用戶操作的轉發。option的結構如下:
interface Op {
type: number // 頁面操作or圖形操作
graph?: {
op: number // 添加、旋轉、縮放、平移
type?: string // 圖形類別
key?: string // 圖形所對應的key
page?: number // 圖形所對應的頁面
content?: any // 圖形內容
}
page?: {
op: number //添加、刪除、切換頁面
key?: number // 頁面對應的key
content?: any // 頁面對應的內容
}
}
這樣的每個option,我們都會存放到操作棧裡面,結合另外一個緩存棧,即可實現撤銷和恢復。
(4)多人協同
對於多人的操作,其實是多個人對多個圖形的操作,人與當前所操作的圖形是一一對應的。
所以我通過一個令牌集的概念,來存放「所有的用戶id」,以及每個用戶當前「所操作的圖形id」,這樣就確定下來個每個用戶正在操作什麼。
不同用戶的操作通過以下流程完成:
- 操作者設定當前所操作圖形的id,並更新令牌集。
- 接收者同步更新令牌集。
- 操作者發送操作數據(option)。
- 接收者根據用戶信息從令牌集中確定所操作的圖形,再根據option修改具體的svg數據。
整體白板從產品的設計到架構的設計就結束了。
歡迎體驗:http://whiterose.cf.since88.cn
前端代碼:https://lab.since88.cn/whiterose/frontend
後端代碼:https://lab.since88.cn/whiteros