JS 拖拽對齊參考線+自動吸附+對齊到網格

具體代碼參見:https://github.com/yyccmmkk/js-reference-line

 

【需求】

對一個元素進行拖拽時,生成這個組件和其它組件對齊的參考線,實現各組件間四條邊及水平中心線及垂直中心線對齊。在拖動完成後實現自動吸附對齊。

【解決思路】

1 MAP記錄所有需要對齊組件的視窗座標點(左上,右上,左下,右下)

2 P爲當前拖拽對象實時的座標點(左上,左下,右上,右下,中心點)

3 拿當前對象的座標點P去匹配座標記錄MAP

4 發現某一邊對齊時,在canvas中畫線,清除畫布的操作應該在拖動時進行處理,

問題的關鍵在於如何快速的去計算當前組件的6條線(四邊+中心線)和其它所有組件6條線在一條線上,看似麻煩其實可以簡化邏輯爲,只要判斷三個點,左上角、右下角、中心點,在記錄中有沒有存在

  1. 如何判斷兩個組件垂直對齊?答:座標x一樣
  2. 如何判斷兩個組件水平對齊?答:座標Y一樣
  3. 如何記錄座標點便於查詢
  4. 根據座標畫線

【答:3】

創建一個數組 tempArry 存放所有的座標對象(包含座標信息),像下邊這樣

let tempArray=[
        {let:1,right:100,top:10,bottom:400},
        {let:2,right:200,top:20,bottom:600},
        {let:1,right:300,top:30,bottom:400}
        ];

創建兩個對象mapX 、mapY。對tempArray 進行遍歷,mapX mapY 分別以x ,y 爲key。 值爲數組(ps:因爲有可能多個組件 座標是相同的),數組保存了座標對象在tempArray中的索引。

mapX 記錄所有組件的座標x,每個組件三個x座標(ps:左、中、右),結果如下

let mapX={
        1:[0,2],
        2:[1],
        50.5:[0],
        101:[1],
        150.5:[2],
        100:[0],
        200:[1],
        300:[2]
    };

mapY 記錄所有組件的座標y,每個組件有三個座標y(ps:上、中、下),結果如下

let mapY={
        10:[0],
        205:[0],
        310:[1],
        215:[2],
        20:[1],
        30:[2],
        400:[0,2],
        600:[1],

    }

 

假設有一組件視窗座標爲(left:1,right:600,top:20,bottom:300);

通過判斷左上角座標點(p1) 就可以檢測組件左邊與上邊的對齊,通過右下角座標點(p2),就可以檢測組件 右邊與下邊的對齊,對過中心座標(p3)就可以找到水平與垂直線的對齊。

p1 x:1,y:20

p2 x:600,y:300

p3 x:300.5,y:160

mapX 中存在以x 爲值的key 就證明有垂直對齊的線,

mapY 中存在以 y爲值 的key 就證明有水平對齊的線

通過map 中的值索引可以快速拿到對應的對齊組件信息,把當前組件的座標點信息扔進去,取最大最小值就可以拿到對齊線的座標信息,詳見源碼,大概思路是這樣,其中還涉及一些細節,比如排自身的座標信息等。

【自動吸附】

移動中的自動吸附功能不但性能開銷高而且相對來說比較複雜,暫時開發爲在拖動完成後進行自動吸附操作。

對於自動吸附可以抒理一下子功能點,

1 在吸附範圍內找到符合的座標點,也就是說 目標點座標 (有3個目標點座標)減掉當前座標點 絕對值不大於吸附範圍

2 在前邊的功能中只要找到三個點就可以,所以吸附功能也要找到當前元素的這三個點座標 及吸附範圍 座標

3 需要區分的是當前元素的哪條邊對齊了,因爲操作作當前元素樣式時,如果底邊或右側的邊對齊了需要減掉元素自身的寬或高

4 需要知道當前移動的方向,當用戶在遠離在吸附範圍內的元素時不要吸附

具體的實現細節詳見代碼

【對齊到網格】

對齊到網格更簡單,在之前的基礎上把網格座標放入需要吸附到的坐點數組裏即可,生成網格x,y座標放入,具體詳見源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章