js 获取鼠标在画布的位置_云凤蝶如何打造媲美 sketch 的自由画布
在 Design Tools 中,組件間的對齊與吸附功能是否好用是決定其畫布是否可以高效進行產品設計的關鍵因素。云鳳蝶作為一款快速制作高品質中后臺應用的 hpaPaaS 平臺,同樣擁有自由拖拽的可視化畫布。那么在云鳳蝶的自由畫布中,對齊規則是怎樣的?實現這些規則的策略是怎樣的?規則和策略是否足夠完備?最終效果如何?能否媲美 Sketch 等設計軟件?這篇文章就來對這些問題進行一一解答。
幾個術語
在開始前,先簡單介紹幾個術語及其在畫布中出現時的樣式。
構成組件的 6 條線可以看到,一個組件在畫布中可以由 6 條線 (vt / vm / vb | hl / hm / hr) 來表示,組件移動過程中的對齊其實就是組件的 6 條線到其它組件線的集合中尋找臨近線,找到后考慮 吸附 + 對齊 的過程。
對齊線間距線間距塊以上是組件在移動過程中對齊時出現的幾種狀態,其中出現 3 個名詞,3 種輔助樣式:
- 紅色實線代表吸附線
- 藍色實線代表距離線
- 粉色塊代表間距塊
通用規則
在介紹云鳳蝶畫布中的對齊規則之前,我們先來直觀地看下當下幾款不錯的設計產品在對齊方面是如何做的。這里主要以 Sketch 和 Figma 這兩款設計工具為例,其它如 FramerX、墨刀等也可自行參考,效果大致相同,只是它們在實現上的優化程度略有高低。
Sketch
Sketch 對齊Sketch 對齊在 Sketch 中,以帶邊框組件的邊框中線為基準,在移動過程中不斷去找到距離最近的線去對齊。其中
- 在首次接近某條線時,有一個吸附的過程。如在移動 1px 找到吸附線時,會讓組件實際移動 6px,達到吸附效果
- 當組件在吸附線上時,再次移動時,考慮是否能找到相鄰的線,如果可以找到,則移動到下條吸附線上;如果未找到時,則鼠標移動某個距離時,觸發移動,有種卡點的感覺,用以輔助對齊;
- 另外還有比較細節的地方,比如當某一個方向移動吸附到相鄰的線后(右圖),如果相反方向移動,則非常輕松,而如果繼續同一方向繼續移動,則需要移動比較大的距離,以此實現了更好的吸附對齊效果。
- ...
Figma
Figma 對齊Figma 對齊在 Figma 中,功能大致相同,與 Sketch 不同的是組件是以外邊框為對齊線,且在組件移動過程中沒有距離線的出現的。
提前劇透:這方面云鳳蝶會有獨特的策略。對比
以上用最簡單的組件移動示例分別展示了 Sketch 和 Figma 這兩款設計產品在組件移動時的一個不斷對齊的過程,核心主要涉及到
- 對齊(與哪些組件邊框線對齊)
- 吸附(多少距離內時吸附)
- 距離(與哪些組件邊框線考慮展示距離)
- 畫線(畫哪幾條線、從哪里出線)
至于它們是如何實現,目前是不了解的,未查找到其完整的策略及算法。但是通過細致的使用,我們可以體驗到這些產品中觸發不同功能的時機、功能的優化以及順暢度等等。另外,這些設計工具中還有有很多其它的輔助功能,如精心設計的快捷鍵、間距塊的輔助、可視區域內的防干擾對齊等等,這里沒有進行展示,下面在介紹云鳳蝶自由畫布中的輔助功能時會有介紹。
Sketch 和 Figma 在設計領域已經算是比較上乘的產品了,通過了解它們,我們可以看到當前設計產品中畫布較好的的使用體驗是怎樣的,以此借鑒來優化我們的畫布體驗。
云鳳蝶規則
好了,前置內容鋪墊結束,到了云鳳蝶畫布這里。云鳳蝶也有可自由拖拽的畫布,還有更豐富的資產支持添加更多樣的組件。不過,我們除了支持上述 Design Tools 中兩條線的預期偏差對齊吸附,還遵循 Ant Design 設計規范中的 Gutter=(8n)px 的原則,所以云鳳蝶畫布中組件在對齊吸附時,還需要在幾個特殊的無形線(8px / 16px / 24px)處做間距卡點吸附。
關于布局、網格單位、柵格等規范,可以參考 Ant Design 官網中 布局 一節進行詳細了解。接下來讓我們詳細來看下云鳳蝶中的規則以及當前已經完成的功能和效果。
對齊吸附
對齊吸附當組件朝某一方向移動時,以上圖中橫向左移動為例,它的 hl / hm / hr 會不斷的去查找與這 3 條線相鄰最近的線。其中
- 當沒有找到相鄰線時,組件跟隨鼠標移動;
- 當初次找到時,組件便移動一個較大距離吸附過去;
- 當在吸附線上再次移動時,繼續查找相鄰線,看是否有下一條吸附線
- 如果有,則移動到下一條吸附線上;
- 如果沒有,則在鼠標移動一定距離后,組件離開;
以上便是組件對齊吸附的時機及規則,這是可自由拖拽畫布中最基礎的一個吸附對齊能力。
間距吸附
間距吸附上文中提到過,在云鳳蝶中搭建頁面時,組件的擺放要遵循 Ant Design 中 (8n)px 的原則,所以在云鳳蝶的自由畫布中也要實現組件間距滿足要求時的吸附能力。
resize 吸附
resize 吸附resize 吸附的使用場景是在調整組件寬高時,想要與目標組件的某條邊線對齊。由上圖也可以看到,對于組件的邊框對齊,我們是做了內外的一個適配,站在用戶搭建使用的角度來,給出對齊提示。
間距塊吸附
間距塊吸附間距塊的對齊吸附更多的是給到用戶一種提示,即橫/縱方向上幾個組件間滿足同等間距。
吸附剪枝
可視區域變化可視區域內組件變化吸附剪枝主要是解畫布中組件太多時組件需要對齊的目標組件太多的問題,該規則依賴于“用戶只關心當前畫布中組件的對齊”這一假設,減少對齊時的干擾。上動圖中主要展示跟隨可視區域變化,其內組件數量變化時的剪枝。
另一種吸附剪枝是在組件快速移動時,也要避免一直找線,干擾正常移動,如下圖中所示。
快速移動時的剪枝快捷鍵
這里簡單舉兩個與輔助線相關功能的快捷鍵 command / option | alt。其實看到后面的實現后就會發現,只要有了這套線的邏輯,想實現類似的功能是比較容易的。
command 鍵標識組件相對位置option/alt 鍵標識任意兩個組件相對位置command 鍵移動組件時無吸附對齊畫線原則
對齊一個組件在對齊時,通常情況下出現的線的條數最多是
- 3 + 3 條 紅色的對齊線
- 2 條 藍色的距離線(藍色線永遠從移動的組件中線出發)
對于 Label
- 橫向線,label 在上
- 縱向線,label 在左
規則原因
這里簡單解釋下,為什么要在畫布中實現吸附對齊能力。
首先,可以回歸到吸附對齊的作用 -- 彌補用戶在精確操作鼠標上的不足。考慮以下場景:當用戶試圖把一個組件精確擺放到另一個組件旁邊時,目標區域只有 1px,當在移動組件時,如何準確擺放到想要的位置?如果沒有吸附對齊的能力,要想實現精確擺放是非常難操作的,要么容易重合,要么容易分離。此時,如果有吸附對齊的能力,就有種讓“目標區域”變大的效果,當拖拽組件與目標組件兩者僅僅相差某個指定范圍的像素時,即認為是進入了吸附對齊的范圍內,直接把移動組件吸附到目標位置上。與此同時,當組件離開時也會有一個“吸附引力”,即也有一個同等的離開距離,以形成卡點效果。這樣,整個對齊操作就比較有控制力了。
同時,這種能力可以讓畫布中組件的擺放更加高效。依賴于 Ant Design 的 Gutter 設計原則,當我們在畫布中進行頁面搭建時,可以比較輕松的擺放到更符合設計原則的位置上去,更快速地搭建頁面,從而達到提效的目標。
實現策略
當我們總結出自由畫布中組件對齊吸附的能力之后,就可以考慮如何實現它。涉及到對齊吸附,一定就涉及到”移動組件“和”目標組件“,下面就從組件移動的角度來大致介紹實現以上規則的一種思路。
存儲
在上文中提到,一個組件可以看做是由 6 條線構成的,組件移動過程中的吸附就是這些線之間的對齊關系。所以,首先要做的就是對組件進行線的存儲。下面是一種可行的存儲數據結構
一條線有自身的 pos、type及其所歸屬的 Box
// 線的數據結構 interface Line {pos: number;type: LineType;box?: Box | null; }一個組件有 6 條線,且冗余存儲其 node 及組件實例信息 instance
// 組件的數據結構 interface Box {id: string;vt: Line;vm: Line;vb: Line;hl: Line;hm: Line;hr: Line;node: HTMLElement;instance: ComponentInstance; }線的存儲可以考慮使用二叉樹,普通二叉樹可以參考 typescript-collections/src/lib/BSTree.ts,而橫縱線可以構造兩顆二叉樹
// 線的集合 interface Lines {vLines: BSTree;hLines: BSTree; }如果你有其它好的思路,可以一起探討,比如桶移動
組件的移動,可以考慮兩種實現方式
- H5 Drag And Drop
- 拖放鼠標事件
其中,H5 DnD 不是移動 HTML 元素,而是將數據對象從一個位置移動到另一個位置。要移動 HTML 元素,必須使用 MouseEvents:
- mousedown: 選中元素
- mousemove: 移動元素
- mouseup: 釋放元素
為了實現更好地拖拽移動效果,我們采用 MouseEvents 的實現方式。決定了如何拖拽以后,接下來就來考慮,如何實現組件的移動。下圖展示了鼠標選中組件時的移動位置關系,其中, A 為鼠標 mousedown 時的選中點,B 為鼠標移動后的 mouseup 的釋放點,moveX 則表示鼠標的移動距離,也即組件即將橫向移動的距離。
鼠標在組件上的移動找線
線的查找與線的存儲數據結構密切相關。在存儲時,我們采用的是二叉樹,所以找線的過程就變成了在二叉樹中查找與某個位置具有某種大小關系的線,具體的找線算法這里不表,只能說根據業務規則盡量找到最優的算法。找線邏輯是整個策略中的關鍵一環,通過合理的策略找出離當前組件最近的線,只有這樣才能保證后面的吸附是正確的。
找線策略在上文對齊吸附中有提到,這里不再贅述。需要說明的是,“離當前組件最近”是需要重點考慮的,因為在橫/縱向查找的過程中,3 條線都有可能遇到最近的線,而且還有 Ant Design Gutter 8xpx 原則在這里,所以這里需要綜合考慮。
吸附
當通過前置步驟找到了要吸附的線,我們就可以考慮是否將組件進行移動吸附了,這里主要還是要結合找到的”最近的線”。不過需要注意的是,我們不能在找到線時就移動過去,是因為組件移動距離與鼠標移動偏差不一致時可能會帶來的抖動。
此外,對于組件在吸附狀態下的移動,也是需要做二次找線的,因為當此時可能直接離開當前的引力區域,也可能是移動到下一條吸附線上。
吸附同樣是非常關鍵的一環,處理不好將直接影響到畫布的使用體驗,處理了上述兩方面,理論上就達到一個不錯的效果。
分類
在文章開頭,給出了幾種不同輔助功能的線,在目前的對齊策略中,有以下幾種
enum PairType {distance = 'distance', // 距離線alignment = 'alignment', // 對齊線spacing = 'spacing', // 間距線area = 'area', // 間距塊 }無論是對齊線、距離線、間距線還是間距塊,都是通過二叉樹中一對 Line 構成的 LinePair 畫出的
export interface LinePair {source: Line; // 需要對齊的邊target: Line; // 可以被對齊的邊type: PairType; // 這對線的關系delta: number; // 這對線的偏差duplicate?: Line[]; // 目標對齊線可能包含多條位置相同的邊框線或者中間線 }根據以上數據結構,我們可以對找到的線進行一個分類,標識出一對線的關系及偏差。
畫線
在以上步驟中拿到分好類的線,就可以進行畫線操作了。通過線的分類及規范的數據結構,我們可以保證各類型線的畫線邏輯的純粹性。然后針對不同類型的線,在畫布中用不同的層來實時展示即可。
至于如何實現更高效的畫線以及用何種技術手段來實現,則可以仁者見仁了。
總結
本文主要總結了當前云鳳蝶自由畫布中支持的對齊、吸附、間距、resize、畫線等輔助功能以及實現這些功能的整體規則和策略,這些都是自由畫布中最基礎的能力,也是推導出畫布中吸附對齊涉及取值的理論基礎。
梳理下來可以看到,要想在自由畫布中實現對齊的能力并不難,麻煩的是如何將規則和策略理清楚、提煉和沉淀,從全局的視角和可擴展的角度來實現。最近云鳳蝶自由畫布中對齊等輔助能力已經根據這些原則進行了 2.0 的升級,從整體使用體驗上,組件擺放這件事情已經變得比較容易。
未來
這里羅列幾點當前云鳳蝶畫布中相較于 Design Tools 中還可以優化的地方:
- 標尺的對齊與吸附(標尺可以看做是只有一條 h / v 方向 height / width 為畫布大小的線)
- 間距塊的查找納入對齊吸附的整體查找策略中(當前是與對齊線、輔助線的查找分開的)
- 無極縮放,在更小的區域也能優雅地實現想要的操作
- 揣測用戶意圖,更“智能”快速的擺放策略
看到上述幾點,感覺也不是很難啊,為啥還沒做?
是的,主要是因為...
等你來,一起做!
參考
- Ant Design 布局https://ant.design/docs/spec/layout-cn
- typescript-collectionshttps://github.com/basarat/typescript-collections/blob/release/src/lib/BSTree.ts
- H5 Drag And Drophttps://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
- MouseEventhttps://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
- Drag'n'Drop with mouse eventshttps://javascript.info/mouse-drag-and-drop
- Drag & Drop vs. MouseEvents - A misunderstandinghttps://steffenjahr.de/2016/02/07/drag-drop-vs-mouse-events-a-missunderstanding/
- Sketchhttps://www.sketch.com/
- Figmahttps://www.figma.com/
未來已來,時不我待!
云鳳蝶招聘前端、Java、PD、設計崗位,未來等你共創!
如果你感興趣,歡迎聯系 chenyu@antfin.com 或 shuai.shao@antfin.com
總結
以上是生活随笔為你收集整理的js 获取鼠标在画布的位置_云凤蝶如何打造媲美 sketch 的自由画布的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用寿命长达100年!特斯拉合作团队研究
- 下一篇: 小米12 Pro天玑版与骁龙8+版齐曝光