前言

在之前的几篇博客文章中,我了解了echart以及一些css布局。

我们需要脑补一些如何能更好的显示数据,使数据易于观察和分析的布局。

布局

对于布局采用类似网格布局的方式;为了能使页面自适应显示,将采用rem进行配置。

网页整体分为两个部分:

  • 头部

  • 主体

头部用来显示一些基本的信息,例如标题、时间、天气等基础信息。

主体用来显示图例和某些重点关注的信息,例如工厂人员情况、设配状况、重要厂房监控等等。

在配置头部和主体布局样式之前,进行全局设置以及body设置。

基础设置

  • 全局设置

    对网页的样式进行初始化,对整体网页的样式进行设置,例如字体、内外边距、盒子范围等等。

    1
    2
    3
    4
    5
    6
    * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    color: #fff;
    }

    这里设置margin: 0; padding: 0;的好处在于清除元素关于该属性自带的样式,因此 table 的默认样式就会改变。

  • body设置

    1
    2
    3
    4
    5
    6
    body {
    height: 100vh;
    font-family: Arial, Helvetica, sans-serif;
    background: url(../img/bg.jpg) no-repeat top center;
    background-size: cover;
    }

    body 显示页面的部分,因此也可以在这里设置背景图,以决定全局布局的颜色。background 的值是一种简写方式:url()背景图、no-repeat不重复背景图像、top center图像水平位置、垂直位置。Arial微软Windows操作系统中常用的字体;Helvetica苹果电脑的默认字体。

头部

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
<header>
<div class="ab-l">
<span class="showtime"></span>
</div>
<script>
// 动态加载时间
// 这个时间会在网站加载1s后显示 并不是网站造成的延迟
// 如果不希望这样,
// 你可以将showTime()不直接写在setInterval()函数里面
// 而是单独写并且单独调用一次
// 再放到setInterval()里面
setInterval(function showTime(){
// var now = (new Date()).toLocaleString();
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth()+1;
var day = now.getDay();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
$('.showtime').text(year+'/'+month+'/'+day+'\t'+hours+':'+minutes+':'+seconds);
}, 1000);
</script>
<h1>自动化综合车间监控</h1>
</header>
1
2
3
4
5
6
7
8
9
10
11
12
13
function showTime(){
// var now = (new Date()).toLocaleString();
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth()+1;
var day = now.getDay();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
$('.showtime').text(year+'/'+month+'/'+day+'\t'+hours+':'+minutes+':'+seconds);
};
showTime();
setInterval(showTime, 1000);

上面的html代码你可以看到h1设置在最下面,如果这里没有为 absolute元素设置属性top: 0;,那么会被h1挤到下面,而将h1放在下面就不会挤走它。

1
2
3
4
5
6
header {
position: relative;
height: 1rem;
background: url(../img/head_bg.png) no-repeat top center;
background-size: 100% 100%;
}

这里设置position: relative;的好处在于可以约束通过absolute浮动的元素

background-size: 100% 100%;的作用在于原图片可以完整显示出来,但同样它有一个缺点就是占多少显示多少,你可以在 body 里面设置这个参数,就知道设置和没有设置这个参数时产生的区别。如果想解决这个没有内容撑开图片不全局显示的问题,可以使用height: 100vh;

height: 1rem;高度是根据父级去进行获取真实值,你可以通过在 flexible.jssetRemUnit() 函数里面看到 rem 相当于将宽度分为10份,如浏览器的宽度为1536px,将其分为10份,那么 1rem = 153.6px

可能你发现header没有配置宽度,那是因为使用一个块级+两个absolute元素的方法。

  • 一个块级:撑起头部内容区域,即标题。
  • 两个absolute元素:左右两边附属信息,即时间、天气等等。

标题

1
2
3
4
5
6
h1 {
line-height: .875rem;
color: #fff;
font-size: .475rem;
text-align: center;
}

h1 用于撑起整个头部,使头部背景图正常显示。这里行高之所以没有设置成 1rem,因为字体看起来会不像是垂直方向的中间。

组件

1
2
3
4
.ab-l {
position: absolute;
left: .45rem;
}

ab-l 可以将元素定义为一个向左的absolute浮动元素,并且与左边离有一定距离。

1
2
3
4
5
.showtime {
font-size: .25rem;
line-height: .75rem;
color: rgba(255, 255, 255, 0.7);
}

span属于行内块元素(不会独占一行,可以自定义高宽),之所以设置是因为内容的需要,可以通过 js 快速编辑。如果有多个组件,可以通过ul->li来设置样式。

右边的absolute元素使用方法和左边一样,只是left: .45rem;变成right: .45rem

主体盒子

1
2
3
4
5
<div class="mainbox">
<div class="row-3"></div>
<div class="row-5"></div>
<div class="row-3"></div>
</div>
1
2
3
4
.mainbox {
padding: .25rem .5rem 0;
display: flex;
}

.mainbox 设置成弹性布局,需要注意的是它的子级对于topbottom这样的值是不起作用的,因此子级位置不推荐设置成 abosolute,但是它的子级以下的元素可以设置且top bottom等生效。

列布局

1
2
3
4
5
6
7
8
9
10
11
12
13
.col-3 {
flex: 3;
}

.col-5 {
flex: 5;
}

.col-3, .col-5 {
margin: 0 .125rem;
/* 在做逻辑层解决缩小宽度不变的情况添加上的 */
overflow: hidden;
}

.col-*将剩余空间分配,即分配.mainbox的内容区域(不包括.mainbox内边距以及.col-*外边距)。左右两边均为3,中间为5,合计11份。

左边.col-3包括:厂房人员监控、产品质检数据、库房库存量监控。

中间.col-5包括:厂房视频监控画面、生产实时监控。

右边.col-3包括:厂房环境监控、厂房设备监控、物料存储数据。

列布局有效区分配计算方式

col-*的有效分配区计算方式:

  1. 减去父级内边距以及内边距以外的盒子参数
    $$
    W_{av}=W-2(W_{p}+W_{b}+W{m})-W_{o}
    $$
    .mainbox没有父级,除了body并且外边距$W_{m}$以及边框$W_{b}$没有设置,只有设置内边距$W_{p}$,因此上面的等式变成了$W_{av}=W-2W_{p}$。

  2. 减去同级设置的所有外边距
    $$
    W_{res} = W_{av}-2nW_{m}
    $$
    条件:同级.row-*外边距$W_{m}$均设置为一样的。$n$为几个同级row-*,左右外边距不会像上下外边距那样(长的将短的包起来)。这里没有设置内边距,且前面设置了box-sizing: border-box;,因此内边距和边框是包含之内的。

  3. 计算.row-1的值
    $$
    W_{row-1} = \frac{W_{res}}{N}
    $$
    $W_{res}$:剩余空间

    $N$:总分数

  4. 计算不同.row-*

    使用$n$代替*以便区别。
    $$
    W_{row-n}=W_{row-1}*n
    $$

面板

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="row-3">
<div class="panel"></div>
<div class="panel"></div>
<div class="panel"></div>
</div>
<div class="row-5">
<div class="panel"></div>
<div class="panel"></div>
</div>
<div class="row-3">
<div class="panel"></div>
<div class="panel"></div>
</div>
1
2
3
4
5
6
.panel {
margin-bottom: .125rem;
padding: .25rem;
background: url(../img/panel.png) no-repeat top center;
background-size: 100% 100%;
}

使用.panel按上面的描述划分数据区域,这样的好处就是更好的查看布局,也方便后面修改。

1
2
3
4
5
<div class="panel">
<div class="panel-head"></div>
<div class="panel-body"></div>
<div class="panel-footer"></div>
</div>
1
2
3
4
.panel-head, .panel-body, .panel-footer {
overflow: hidden;
position: relative;
}

设置panel-headpanel-bodypanel-footer,它们三个没有实际样式,这是便于存储多个图例以及更好的展示除了图例以外的东西。

我的原则是尽量降低代码深度,因此大部分情况我都是使用图例解决的。

mainbox-panel-left

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="col-3">
<!-- 厂房人员监控 -->
<div class="panel">
<div class="panel-body">
<div id="department"></div>
</div>
</div>
<!-- 产品质检数据 -->
<div class="panel">
<div class="panel-body">
<div id="quality"></div>
</div>
<div class="panel-footer">
<div id="quality-footer"></div>
</div>
</div>
<!-- 库房库存量监控 -->
<div class="panel">
<div class="panel-body">
<div id="stock"></div>
</div>
</div>
</div>
1
2
3
4
5
/* 厂房人员监控 */
#department{
width: 100%;
height: 1.625rem;
}

厂房人员监控主要用于显示当前厂房的人数,以便监视厂房人员流动。

1
2
3
4
5
6
7
8
9
10
/* 产品质检数据 */
#quality {
width: 100%;
height: 1.625rem;
}
/* 产品质检数据页脚info */
#quality-footer {
width: 100%;
height: 1.625rem;
}

产品质检数据用于显示每个产品的质量走势。

产品质检数据页脚用于显示每个产品检测出的数据。

1
2
3
4
5
/* 库房库存量监控 */
#stock {
width: 100%;
height: 3.45rem;
}

库房库存量监控用于实时了解当下物料的使用情况。

1
2
3
4
5
/* 厂房视频监控画面 */
#workspace-mon {
width: 100%;
height: 6.5rem;
}

厂房视频监控画面用于查看当下机器的实时工作状态。

1
2
3
4
5
/* 生产实时监控 */
#produce {
width: 100%;
height: 2.45rem;
}

生产实时监控用于查看当下物料的使用数据与产品销售订单。

1
2
3
4
5
/* 厂房环境监控 */
#condition {
width: 100%;
height: 2.65rem;
}

厂房环境监控用于检测当下厂房的情况。

1
2
3
4
5
6
7
8
9
10
/* 厂房设备监控头部info */
#machines-head {
width: 100%;
height: 1.85rem;
}
/* 厂房设备监控 */
#machines {
width: 100%;
height: 2.45rem;
}

厂房设配监控用于监控不同厂房的设配状态。

厂房设备监控头部用于选择当下厂房的机器。

1
2
3
4
5
/* 物料存储数据 */
#material {
width: 100%;
height: 3.02rem;
}

物料存储数据用于显示当前物料的存储情况。

后面觉得不理想的地方可以在进行维调。

效果图

这个布局效果还是存在一定问题,对于部分设备不能正常显示布局效果,目前还没有解决手机端的问题。

【效果图网址】