在七牛云校园黑客马拉松中,一款设计优良、逻辑清晰的白板作品怀才不遇,取得第二名的好问题,这就是来自郑州大学 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/whiter… 后端代码:https://lab.since88.cn/whiteros