大屏定位解决方案
此解决方案主要是为了解决大屏布局定位的方式
# 解决方案
- 使用传统布局方式
- 绝对定位方式
- Grid 布局方式
最后决定使用绝对定位方式主要考虑到会出现中间空白,两边布局的方式,绝对定位的方式会更加灵活
脚手架下载索引:screenPot
# 实现
# 样式布局
如果使用绝对定位,先使用 css 保证父元素的宽高和设置元素的原始定位
<style>
html,
body {
height: 100%;
width: 100%;
margin: 0;
}
.big-screen {
height: 100%;
width: 100%;
margin: 0;
position: relative;
}
.big-screen > div {
background-color: pink;
position: absolute;
border: 1px solid royalblue;
box-sizing: border-box;
font-size: 20px;
text-align: center;
line-height: 1;
height: 0;
width: 0;
top: 50%;
left: 50%;
transition: all 0.5s;
}
</style>
</head>
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
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
# 定位方式
使用自定义属性来定义元素的位置和大小
<body>
<div id="screen" class="big-screen">
<div top="0" left="0" height="300" width="500">1</div>
<div top="300" left="0" height="400" width="500">2</div>
<div top="700" left="0" height="380" width="500">3</div>
<div top="0" left="500" height="750" width="920">4</div>
<div top="750" left="500" height="330" width="920">5</div>
<div top="0" left="1420" height="300" width="500">6</div>
<div top="300" left="1420" height="400" width="500">7</div>
<div top="700" left="1420" height="380" width="500">8</div>
</div>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
// 可以设置初始化位置的时间
let bigScreen = new SreenPot(document.getElementById("screen"), {
gutter: 20,
init: true,
});
1
2
3
4
5
2
3
4
5
//设置屏幕宽高,默认获取浏览器宽高
let bigScreen = new SreenPot(document.getElementById("screen"), {
deviseHeight: 1080,
devisetWidth: 1920,
gutter: 20,
});
bigScreen.init();
1
2
3
4
5
6
7
2
3
4
5
6
7
# 实现原理
- 传递父元素,获得子元素列表
- 根据子元素获取自定义属性来计算
- 为了适配不同设计图,可以传递设计图的宽高和默认间距
- 计算宽高和定位的百分比,然后设置属性,留出间距
# 实现代码
!(function (global) {
"use strict";
class SreenPot {
$el = null;
$options = {};
constructor(el, options = {}) {
this.$options = options;
this.$el = el;
if (options.init) {
this.init();
}
}
init() {
let parts = this.$el.children;
for (const part of parts) {
this.setPosition(part);
}
}
setPosition(el) {
let { top, left, height, width } = this.getPoit(el);
let style = {
top: `calc(${top})`,
left: `calc(${left})`,
height: `calc(${height})`,
width: `calc(${width})`,
};
this.setAttr(el, style);
}
getPoit(el) {
let {
deviseHeight = document.body.clientHeight || 1080,
devisetWidth = document.body.clientWidth || 1920,
gutter = 20,
} = this.$options;
let keys = ["top", "height", "left", "width"];
let poit = keys.reduce((total, current) => {
total[current] = this.getAttr(el, current, true);
return total;
}, {});
let { top, left, height, width } = poit;
let mwgutt = width + left >= devisetWidth ? gutter * 2 : gutter;
let mhgutt = height + top >= deviseHeight ? gutter * 2 : gutter;
top = `${this.getPrecent(top, deviseHeight)} + ${gutter}px`;
left = `${this.getPrecent(left, devisetWidth)} + ${gutter}px`;
height = `${this.getPrecent(height, deviseHeight)} - ${mhgutt}px`;
width = `${this.getPrecent(width, devisetWidth)} - ${mwgutt}px`;
return { top, left, height, width };
}
setAttr(el, style) {
for (const key of Object.keys(style)) {
el.style[key] = style[key];
}
}
getAttr(el, attr, isNumber) {
let attrCount = el.getAttribute(attr);
if (attrCount === undefined || attrCount === null) {
throw new Error(`${attr}属性未查到`);
}
return isNumber ? Number(attrCount) : attrCount;
}
getPrecent(nume, deno) {
return (nume / deno) * 100 + "%";
}
}
if (typeof define === "function") {
define(function () {
return SreenPot;
});
} else {
global.SreenPot = SreenPot;
}
})(this);
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
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
interface Options {
deviseHeight: number;
devisetWidth: number;
gutter: number;
}
interface Poit {
height: number;
width: number;
top: number;
left: number;
}
interface Poits {
height: string;
width: string;
top: string;
left: string;
}
class SreenPot {
private $el: any;
private $options: Options;
constructor(el, options: Options) {
this.$options = options;
this.$el = el;
if (options.init) {
this.init();
}
}
init() {
let parts = this.$el.children;
for (const part of parts) {
this.setPoit(part);
}
}
private setPoit(el) {
let { top, left, height, width } = this.getPoit(el);
let style = {
top: `calc(${top})`,
left: `calc(${left})`,
height: `calc(${height})`,
width: `calc(${width})`,
};
this.setAttr(el, style);
}
private getPoit(el): Poits {
let {
deviseHeight = document.body.clientHeight || 1080,
devisetWidth = document.body.clientWidth || 1920,
gutter = 20,
} = this.$options;
let poit: Poit = {
left: this.getAttr(el, "left"),
top: this.getAttr(el, "top"),
height: this.getAttr(el, "height"),
width: this.getAttr(el, "width"),
};
let { top, left, height, width } = poit;
let mwgutt = width + left >= devisetWidth ? gutter * 2 : gutter;
let mhgutt = height + top >= deviseHeight ? gutter * 2 : gutter;
let result: Poits = {
top: `${this.getPrecent(top, deviseHeight)} + ${gutter}px`,
left: `${this.getPrecent(left, devisetWidth)} + ${gutter}px`,
height: `${this.getPrecent(height, deviseHeight)} - ${mhgutt}px`,
width: `${this.getPrecent(width, devisetWidth)} - ${mwgutt}px`,
};
return result;
}
private setAttr(el, style: object) {
for (const key of Object.keys(style)) {
el.style[key] = style[key];
}
}
private getAttr(el, attr: string): number {
let attrCount = el.getAttribute(attr);
if (attrCount === undefined || attrCount === null) {
throw new Error(`${attr}属性未查到`);
}
return Number(attrCount);
}
private getPrecent(nume: number, deno: number): string {
return (nume / deno) * 100 + "%";
}
}
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
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
上次更新: 2024/01/18, 10:44:15