logo头像

技术引领生活!

巧用grid布局交换div位置

本文于750天之前发表,文中内容可能已经过时。

经过搜索大部分都是给出使用js来设置css的style属性,这样每个元素还要计算位置,非常不方便,同时可能导致页面混乱

grid布局

阮一峰大神的博客里面啥都有

下面说一下这种特殊定位布局的方法
布局图
观察一下上图可以发现可以将父级div分为3x4的其中4号元素占用两行两列

  1. 声明父级元素为grid
  2. 指定列数为4列
  3. 指定行数为3行
  4. 指定元素的布局见gridpos4 中grid-column(2 / span 2)意思是 从第二列开始,然后跨越两行

注意: 在vue中的less语法经过测试和大神的有出入 (grid-column: 2 / 4; 会报错)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;

width: 400px;
height: 300px;
}

.gridpos4 {
grid-column: 2 / span 2;
grid-row: 1 / span 2;
}

元素交换位置

  1. 使用transform动画 参见项目

使用transform

关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="flex-container column">
<div class="item one" @click="clickChart('1')" style="transform: translate(-22.4%,-33.5%) scale(0.33)">
<multipleColumn></multipleColumn>
</div>
<div class="item two" @click="clickChart('2')" style="transform: translate(-22.4%,0.5%) scale(0.33)">
<column></column>
</div>
<div class="item three" @click="clickChart('3')" style="transform: translate(-22.4%,34.5%) scale(0.33)">
<v-line></v-line>
</div>
<div class="item four active" @click="clickChart('4')" style="transform: translate(43.7%, 0) scale(1)">
<point></point>
</div>
</div>

优点就不说了,下面说点不方便的地方

  • 要每次写定每个元素的位置,这个还真不好计算
  • 切换只是transform等比例放大缩小显示效果(这样放大时可能会早晨模糊)
  1. 我的方法
    既然巴拉巴拉说了人家的不足,show my code, 简单解释下核心思路,因为可以通过grid-column以及grid-row来指定每个元素的位置,于是在鼠标点击的时候来改变类简单时间交换两个元素的位置

效果展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>

<meta name="robots" content="noindex">
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
#container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;

width: 400px;
height: 300px;
}

.gridpos1 {
grid-column: 1;
grid-row: 1;
}

.gridpos2 {
grid-column: 4;
grid-row: 1;
}

.gridpos3 {
grid-column: 1;
grid-row: 2;
}

.gridpos4 {
grid-column: 2 / span 2;
grid-row: 1 / span 2;
transition: all 4s ease-in-out;
transform: rotateY(360deg) scale(0.5) scale(2);
animation: move 2s;
/* transform: scale(2.0) scale(0.5); */
}

.gridpos5 {
grid-column: 4;
grid-row: 2;
}

.gridpos6 {
grid-column: 1;
grid-row: 3;
}

.gridpos7 {
grid-column: 2;
grid-row: 3;
}

.gridpos8 {
grid-column: 3;
grid-row: 3;
}

.gridpos9 {
grid-column: 4;
grid-row: 3;
}

/* 声明动画 关键帧 @keyframes 动画名称{} */
@keyframes move {
from {
opacity: 0.2;
}

to {
opacity: 1;
}
}

.item {
font-size: 4em;
text-align: center;
border: 1px solid #e5e4e9;
overflow: hidden;
}

.item-1 {
background-color: #ef342a;
}

.item-2 {
background-color: #f68f26;
}

.item-3 {
background-color: #4ba946;

}

.item-4 {
background-color: #0376c2;
}

.item-5 {
background-color: #c077af;
}

.item-6 {
background-color: #f8d29d;
}

.item-7 {
background-color: #b5a87f;
}

.item-8 {
background-color: #d0e4a9;
}

.item-9 {
background-color: #4dc7ec;
}
</style>
</head>

<body>
<div id="container">
<div class="item item-1 gridpos1" onclick="clickf(1)">1</div>
<div class="item item-2 gridpos2" onclick="clickf(2)">2</div>
<div class="item item-3 gridpos3" onclick="clickf(3)">3</div>
<div class="item item-4 gridpos4" onclick="clickf(4)">4</div>
<div class="item item-5 gridpos5" onclick="clickf(5)">5</div>
<div class="item item-6 gridpos6" onclick="clickf(6)">6</div>
<div class="item item-7 gridpos7" onclick="clickf(7)">7</div>
<div class="item item-8 gridpos8" onclick="clickf(8)">8</div>
<div class="item item-9 gridpos9" onclick="clickf(9)">9</div>
</div>

<script>
window.lastIndex = 4;

function clickf(p) {
let ele = document.getElementsByClassName(`item-${p}`)[0];
let centerEle = document.getElementsByClassName(`item-${lastIndex}`)[0];

let posName = "";
let eleClassList = ele.classList;
for (let i = 0; i < eleClassList.length; i++) {
if (eleClassList[i].indexOf("gridpos") !== -1) {
posName = eleClassList[i];
break;
}
}

if (posName === "gridpos4") {
console.log("点击了中间")
return;
}

//1. 被点击和中间先移除
ele.classList.remove(posName);
centerEle.classList.remove("gridpos4")

//2.各自增加
ele.classList.add("gridpos4");
centerEle.classList.add(posName);
window.lastIndex = p;

}
</script>
</body>

</html>

PS

很久都没ps了,在和echarts结合的时候需要注意两点

  1. 在切换grid位置完成的时候,要发送一个resize事件,当然前提是每个echart要绑定页面大小改变resize事件,这里不展开说
    1
    2
    let myEvent = new Event('resize');
    window.dispatchEvent(myEvent);
  2. 请注意上例中的 overflow: hidden; 这句不然会造成页面的布局混乱
支付宝打赏 微信打赏

您的支持是我前行的动力!