基於JS快速生成各種網格佈局工具Grid介紹

雲荒杯傾發表於2018-01-15

作者:雲荒杯傾

寫在前面

這兩天瞭解了一下css的grid佈局,發現確實很好用。看了幾篇部落格,瞭解了它的幾個常用屬性後,可以快速生成一個網格佈局。相較於傳統的float、定位等顯得更成體系,更規範,不需要一些hack做法。

雖然grid佈局已經很好,前端工程師中有一些更多是喜歡通過動態建立div,使用js給div加樣式這種方式來完成自己的工作的。

同樣是出於使用JavaScript動態生成grid佈局的需要,誕生了Grid.js這個小工具。

Grid簡介

Grid.js是一個使用JavaScript動態建立規則網格佈局、非規則網格佈局的模組。FE可以通過new Grird(option)建立一個Grid例項, 該例項的UI就呈現為css grid佈局。

效果圖

先來幾張使用Grid.js生成的效果圖吧。 以下四張效果圖父容器的大小都是600*600畫素。

第一張是一個4X4的網格,其中有3個網格是非原子大小(1X1)的,即2X2, 2X2, 2X1。

基於JS快速生成各種網格佈局工具Grid介紹

第二張是一個5X5的規則網格,所謂規則網格就是所有子元素都是1X1的大小。

基於JS快速生成各種網格佈局工具Grid介紹

第三張是一個6X5的網格,其中有5個非原子大小的網格。

基於JS快速生成各種網格佈局工具Grid介紹

第四張是一個7X7的網格,其中有4個非原子大小的網格。

基於JS快速生成各種網格佈局工具Grid介紹

Grid.js使用

Grid.js使用es6 class語法完成,所以使用方式很簡單。 通過new Grid(option)即可生成一個網格例項。就以效果圖第二張圖生成的5X5網格來說,它的程式碼就是:

let grid = new Grid({
            container:document.getElementsByClassName('grid')[0],// 必須項
            colCount:5,
            rowCount:5,
            width:600,
            height:600,
        });
複製程式碼

如果你想給每個網格設定不同的樣式,就是用對外API方法setGridStyleByIndex(); 同樣拿效果圖5X5網格來說,那五個對角線上網格就做了背景的樣式設定,它們是通過如下程式碼完成的:

grid.setGridStyleByIndex(0, {"background": "red"});
grid.setGridStyleByIndex(6, {"background": "green"});
grid.setGridStyleByIndex(12, {"background": "yellow"});
grid.setGridStyleByIndex(18, {"background": "blue"});
grid.setGridStyleByIndex(24, {"background": "orange"});
複製程式碼

還有一個問題是怎麼拿每個子元素(小格子)的引用?通過對外API方法 getGrid(n)。 還有一個問題是怎麼拿所有子元素(小格子)的引用?通過對外API方法 getGrids()

let grids = grid.getGrids();
for(let i = 0; i < grids.length; i++){
    grids[i].innerHTML = i + 1;
}
複製程式碼

上面這段程式碼就是拿了所有小網格的引用,然後給網格填充文字內容的。示例中每個小格子的文字內容就是每個小格子在div列表中的索引+1。

Grid.js API

考慮到最核心的需求有兩點,一個是較為簡單地(至少和直接使用css同樣方便)生成網格佈局,第二是生成網格佈局後拿到每個格子的引用,給格子新增內容。所以主要說這兩方面。

傳參生成網格例項

怎麼生成不同的、規則的、不規則的網格例項,主要看new Grid(option)的時候你傳的引數,提供可傳的引數包括以下。

名稱 型別 簡介
container htmlDomElement 父容器,必須項
rowCount number 網格行數
colCount number 網格列數
width number、% 父容器寬度
height number、% 父容器高度
divCount number 實際格子的多少
gridArea Array 那些非1X1格子的佔位表示

關於divCount和gridArea陣列的說明: 這兩個引數用來生成不規則網格佈局,所以是本模組的關鍵。否則,你就只能用本模組生成n*m的規則網格了。

我們拿第一張效果圖4X4網格舉例,本來如果不是1、2、3那三個網格有跨行、跨列的行為,就不需要傳divCount,也不用傳gridArea,模組會為你生成4X4=16個一模一樣的格子。但是由於這三個較大網格存在,所以,這個父容器是容不下16個子元素的,所以,你傳的divCount是什麼呢,是在存在非1X1子網格的情況下,父容器正好填滿時,子網格的數量,因此就是9.。一般在你拿到設計圖的時候,你就知道這個佈局了,子網格數目很好算(因為實際場景也不需要建立好幾十乘以好幾十那麼瑣碎的格子)。

針對這三個非1X1的子網格,我們需要為其每一個傳一個陣列,來表示這個子網格是在父網格的第幾行開始、第幾列開始、跨幾行、跨幾列。即每個非1X1的子網格,都要傳一個length為4的陣列。然後把這些陣列再放到一個外包陣列裡面,這個外包陣列就是gridArea。

對於效果圖1,gridArea = [[1,1,2,2],[2,3,2,2],[4,1,1,2]]。 整個4X4網格共有3個非1X1大小的子網格。 其中[1,1,2,2]就說明這個4X4的網格中有一個從第一行第一列開始,跨行跨列都為2的子網格。

API介面

目前暴露的API

名稱 引數型別 簡介
setGridStyleByIndex(n,style) number,obj 設定小格子樣式,第一個引數是小格子索引;style是物件,舉例style={"color":"red"}
getGrids() 獲取所有子網格div引用
getGrid(n) number 獲取某個子網格

最後

這個模組可能還不完善,歡迎大家提出寶貴意見。

歡迎關注,GitHub地址,

請戳這裡

另附: 作者部落格

相關文章