案例:立可得-智能看板
项目介绍
-
应对现在数据可视化的趋势,越来越多企业需要在很多场景(营销数据,生产数据,用户数据)下使用,可视化图表来展示体现数据,让数据更加直观,数据特点更加突出。我们引入 ‘立可得’ 数据可视化项目。
-
该项目除了使用了基础的DIV+CSS布局,还引入了一些C3技术,还引入了各类图表的绘制,以及高级的地图数据可视化案例。主要功能有:饼状图、柱状图、线形图、地图 …
使用技术
完成该项目需要具备以下知识:
- div + css 布局
- flex 布局
- css3动画
- css3渐变
- css3边框图片
- 原生js + jquery 使用
- rem适配
- echarts基础
数据可视化项目适配方案
项目需求
- 设计稿是1920px
- PC端适配: 宽度在 1024~1920之间页面元素宽高自适应
适配方案
第一步:修改flexible.js
把屏幕分为 24 等份
// set 1rem = viewWidth / 24 此时我们把屏幕平均划分为24等份
function setRemUnit() {
var rem = docEl.clientWidth / 24
docEl.style.fontSize = rem + 'px'
}
第二步:修改cssrem
插件的基准值为 80px
第三步:要把屏幕宽度约束在1024~1920之间有适配
// 实现rem适配
@media screen and (max-width: 1024px) {
html {
font-size: 42.66px !important;
}
}
@media screen and (min-width: 1920px) {
html {
font-size: 80px !important;
}
}
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>项目适配方案</title>
<script src="js/flexible.js"></script>
<style>
@media screen and (max-width: 1024px) {
html {
font-size: 42.66px !important;
}
}
@media screen and (min-width: 1920px) {
html {
font-size: 80px !important;
}
}
div {
width: 2.5rem;
height: 2.5rem;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
项目准备
项目结构:
首页初始化:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据可视化项目</title>
<link rel="stylesheet" href="css/index.css" />
<script src="js/echarts.min.js"></script>
<script src="js/flexible.js"></script>
<script src="js/jquery.min.js"></script>
</head>
<body>
123
</body>
</html>
body-viewport
制作&column
列容器
- 效果图: 1920px * 1078px
- body 设置背景图 ,行高1.15
- viewport 主体容器,限制最小宽度1024px,与最大宽度1920px,最小高度780px。
- 需要居中显示
- 使用
logo.png
做为背景图,在容器内显示- 内间距
88px 20px 0
- column 列容器,分三列,占比
3:4:3
- 中间容器外间距
32px 20px 0
index.html
结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<!-- 父容器大盒子 -->
<div class="viewport">
<div class="column">1</div>
<div class="column">2</div>
<div class="column">3</div>
</div>
</body>
</html>
index.css
样式:
/*清除元素默认的内外边距 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*让所有斜体 不倾斜*/
em,
i {
font-style: normal;
}
/*去掉列表前面的小点*/
li {
list-style: none;
}
/*图片没有边框 去掉图片底侧的空白缝隙*/
img {
border: 0; /*ie6*/
vertical-align: middle;
}
/*让button 按钮 变成小手*/
button {
cursor: pointer;
}
/*取消链接的下划线*/
a {
color: #666;
text-decoration: none;
}
a:hover {
color: #e33333;
}
/* 基础布局 */
body{
background: url(../images/bg.jpg) no-repeat 0 0 / cover;
}
.viewport{
max-width: 1920px;
min-width: 1024px;
margin: 0 auto;
min-height: 780px;
padding: 1.1rem 0.25rem 0;
background: url(../images/logo.png) no-repeat 0 0 / contain;
display: flex;
}
.column{
flex: 3;
backgroud-color:pink
}
.column:nth-child(2){
flex: 4;
}
公用面板样式
切割示例图
border-image-slice
: 按照 上右下左 顺序切割
面板 .panel
- 容器 .inner 内边距是 上下24px 左右 36px
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<!-- 父容器大盒子 -->
<div class="viewport">
<div class="column">
<div class="panel">
<div class="inner">123</div>
</div>
</div>
<div class="column">2</div>
<div class="column">3</div>
</div>
</body>
</html>
index.css
/* 公共面板样式 */
.panel {
position: relative;
border: 15px solid transparent;
border-width: 0.6375rem 0.475rem 0.25rem 1.65rem;
border-image-source: url(../images/border.png);
border-image-slice: 51 38 20 132;
margin-bottom: 0.25rem;
}
.inner {
position: absolute;
top: -0.6375rem;
left: -1.65rem;
right: -0.475rem;
bottom: -0.25rem;
padding: 0.3rem 0.45rem;
}
.panel h3 {
font-size: 0.25rem;
color: #fff;
font-weight: 400;
}
概览区域(overview)-布局
样式描述:
- 容器高度 110px
- h4字体 28px #fff 左边距 4.8px 下间隙 8px
- span字体 16px #4c9bfd
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据可视化项目</title>
<link rel="stylesheet" href="fonts/icomoon.css" />
<link rel="stylesheet" href="css/index.css" />
<script src="js/echarts.min.js"></script>
<script src="js/flexible.js"></script>
<script src="js/jquery.min.js"></script>
</head>
<body>
<!-- 父容器大盒子 -->
<div class="viewport">
<div class="column">
<!-- 概览区域模块制作 -->
<div class="panel overview">
<div class="inner">
<ul>
<li>
<h4>2,190</h4>
<span>
<i class="icon-dot" style="color: #006cff"></i>
设备总数
</span>
</li>
<li class="item">
<h4>190</h4>
<span>
<i class="icon-dot" style="color: #6acca3"></i>
季度新增
</span>
</li>
<li>
<h4>3,001</h4>
<span>
<i class="icon-dot" style="color: #6acca3"></i>
运营设备
</span>
</li>
<li>
<h4>108</h4>
<span>
<i class="icon-dot" style="color: #ed3f35"></i>
异常设备
</span>
</li>
</ul>
</div>
</div>
</div>
<div class="column">2</div>
<div class="column">3</div>
</div>
</body>
</html>
index.css
/*清除元素默认的内外边距 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*让所有斜体 不倾斜*/
em,
i {
font-style: normal;
}
/*去掉列表前面的小点*/
li {
list-style: none;
}
/*图片没有边框 去掉图片底侧的空白缝隙*/
img {
border: 0; /*ie6*/
vertical-align: middle;
}
/*让button 按钮 变成小手*/
button {
cursor: pointer;
}
/*取消链接的下划线*/
a {
color: #666;
text-decoration: none;
}
a:hover {
color: #e33333;
}
h4 {
font-weight: 400;
}
body {
background: url(../images/bg.jpg) no-repeat 0 0 / cover;
/* background-size: cover; */
}
/* // 实现rem适配 */
@media screen and (max-width: 1024px) {
html {
font-size: 42.66px !important;
}
}
@media screen and (min-width: 1920px) {
html {
font-size: 80px !important;
}
}
.viewport {
display: flex;
min-width: 1024px;
max-width: 1920px;
margin: 0 auto;
padding: 1.1rem 0.25rem 0;
background: url(../images/logo.png) no-repeat 0 0 / contain;
min-height: 780px;
}
.viewport .column {
flex: 3;
}
.viewport .column:nth-child(2) {
flex: 4;
margin: 0.4rem 0.25rem 0;
}
/* 公共面板样式 */
.panel {
position: relative;
border: 15px solid transparent;
border-width: 0.6375rem 0.475rem 0.25rem 1.65rem;
border-image-source: url(../images/border.png);
border-image-slice: 51 38 20 132;
margin-bottom: 0.25rem;
}
.inner {
position: absolute;
top: -0.6375rem;
left: -1.65rem;
right: -0.475rem;
bottom: -0.25rem;
padding: 0.3rem 0.45rem;
}
.panel h3 {
font-size: 0.25rem;
color: #fff;
font-weight: 400;
}
/* 概览区域模块制作 */
.overview {
height: 1.375rem;
}
.overview ul {
display: flex;
justify-content: space-between;
}
.overview ul li h4 {
font-size: 0.35rem;
color: #fff;
margin: 0 0 0.1rem 0.06rem;
}
.overview ul li span {
font-size: 0.2rem;
color: #4c9bfd;
}
监控区域(monitor)-布局
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据可视化项目</title>
<link rel="stylesheet" href="fonts/icomoon.css" />
<link rel="stylesheet" href="css/index.css" />
<script src="js/echarts.min.js"></script>
<script src="js/flexible.js"></script>
<script src="js/jquery.min.js"></script>
</head>
<body>
<!-- 父容器大盒子 -->
<div class="viewport">
<div class="column">
<!-- 概览区域模块制作 -->
<div class="panel overview">
<div class="inner">
<ul>
<li>
<h4>2,190</h4>
<span>
<i class="icon-dot" style="color: #006cff"></i>
设备总数
</span>
</li>
<li class="item">
<h4>190</h4>
<span>
<i class="icon-dot" style="color: #6acca3"></i>
季度新增
</span>
</li>
<li>
<h4>3,001</h4>
<span>
<i class="icon-dot" style="color: #6acca3"></i>
运营设备
</span>
</li>
<li>
<h4>108</h4>
<span>
<i class="icon-dot" style="color: #ed3f35"></i>
异常设备
</span>
</li>
</ul>
</div>
</div>
<!-- 监控区域模块制作 -->
<div class="panel monitor">
<div class="inner">
<div class="tabs">
<a href="javascript:;" class="active">故障设备监控</a>
<a href="javascript:;">异常设备监控</a>
</div>
<div class="content" style="display: block;">
<div class="head">
<span class="col">故障时间</span>
<span class="col">设备地址</span>
<span class="col">异常代码</span>
</div>
<div class="marquee-view">
<div class="marquee">
<div class="row">
<span class="col">20180701</span>
<span class="col">11北京市昌平西路金燕龙写字楼</span>
<span class="col">1000001</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190601</span>
<span class="col">北京市昌平区城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190704</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000003</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20180701</span>
<span class="col">北京市昌平区建路金燕龙写字楼</span>
<span class="col">1000004</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000005</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000006</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建西路金燕龙写字楼</span>
<span class="col">1000007</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000008</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000009</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190710</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000010</span>
<span class="icon-dot"></span>
</div>
</div>
</div>
</div>
<div class="content">
<div class="head">
<span class="col">异常时间</span>
<span class="col">设备地址</span>
<span class="col">异常代码</span>
</div>
<div class="marquee-view">
<div class="marquee">
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000001</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190701</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190703</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190704</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190705</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190706</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190707</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190708</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190709</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
<div class="row">
<span class="col">20190710</span>
<span class="col">北京市昌平区建材城西路金燕龙写字楼</span>
<span class="col">1000002</span>
<span class="icon-dot"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="column">2</div>
<div class="column">3</div>
</div>
</body>
</html>
监控区域 monitor 大盒子的高度是 480px
结构解释:
- .tabs 标签选项 加上active激活选项 默认激活第一个选项
- .content 切换内容 加上
style="display: block;"
显示内容 默认激活第一个内容样式描述:
- .inner 容器内间距 24px 0
- .tabs 容器内间距 0 36px
- a 容器 颜色: #1950c4 内间距:0 27px 字体:18px
- 第一个a容器 去除左侧内间距 加上右侧2px宽度边框#00f2f1
- 激活的时候 颜色白色
- .content容器
- 占满剩余高度 flex:1
- 默认隐藏
- .head 容器
- 行高 1.05 背景 rgba(255, 255, 255, 0.1) 内间距 12px 36px 颜色 #68d8fe 字体大小 14px
- row 容器
- 行高 1.05 内间距 12px 36px 颜色 #68d8ff 字体大小 12px
- .icon-dot 字体图标 绝对定位 左边0.2rem 透明度0
- 鼠标经过后:背景 rgba(255, 255, 255, 0.1) 透明度1
- col容器
- 宽度:1rem 2.5rem 1rem
- 第二个col 一行不换行 溢出 省略
index.css
/* 监控区域模块制作 */
.monitor {
height: 6rem;
}
.monitor .inner {
padding: 0.3rem 0;
display: flex;
flex-direction: column;
}
.monitor .tabs {
padding: 0 0.45rem;
margin-bottom: 0.225rem;
display: flex;
}
.monitor .tabs a {
color: #1950c4;
font-size: 0.225rem;
padding: 0 0.3375rem;
}
.monitor .tabs a:first-child {
padding-left: 0;
border-right: 0.025rem solid #00f2f1;
}
.monitor .tabs a.active {
color: #fff;
}
.monitor .content {
flex: 1;
position: relative;
display: none;
}
.monitor .head {
display: flex;
justify-content: space-between;
line-height: 1.05;
background-color: rgba(255, 255, 255, 0.1);
padding: 0.15rem 0.45rem;
color: #68d8fe;
font-size: 0.175rem;
}
.monitor .marquee-view {
position: absolute;
top: 0.5rem;
bottom: 0;
width: 100%;
overflow: hidden;
}
.monitor .row {
display: flex;
justify-content: space-between;
line-height: 1.05;
font-size: 0.15rem;
color: #61a8ff;
padding: 0.15rem 0.45rem;
}
.monitor .row .icon-dot {
position: absolute;
left: 0.2rem;
opacity: 0;
}
.monitor .row:hover {
background-color: rgba(255, 255, 255, 0.1);
color: #68d8fe;
}
.monitor .row:hover .icon-dot {
opacity: 1;
}
.monitor .col:first-child {
width: 1rem;
}
.monitor .col:nth-child(2) {
width: 2.5rem;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.monitor .col:nth-child(3) {
width: 1rem;
}
监控区域-效果
切换功能:
- 绑定 标签页点击 事件
- 当前容器加active其他容器移除active
- index对应的内容容器显示其他容器隐藏
//新建js/index.js,添加如下代码 ,然后在index.html中引入
// 切换
(function() {
//立即执行函数
$(".monitor .tabs").on("click", "a", function() {
$(this).addClass("active").siblings("a").removeClass("active");
// console.log($(this).index());
// 选取对应索引号的content
$(".monitor .content").eq($(this).index()).show().siblings(".content").hide();
});
})();
无缝滚动实现思路:
- 先克隆列表,追加在后面
- 使用CSS3的
animation
实现动画- 使用
translateY
向上位移 50% - 动画时间15s,匀速播放,循环执行
- 使用
- 鼠标经过,暂停
添加到index.js的立即执行函数中
// 监控区域模块制作
(function() {
$(".monitor .tabs").on("click", "a", function() {
$(this)
.addClass("active")
.siblings("a")
.removeClass("active");
// console.log($(this).index());
// 选取对应索引号的content
$(".monitor .content")
.eq($(this).index())
.show()
.siblings(".content")
.hide();
});
// 1. 先克隆marquee里面所有的行(row)
$(".marquee-view .marquee").each(function() {
// console.log($(this));
var rows = $(this)
.children()
.clone();
$(this).append(rows);
});
})();
index.css
/* 通过CSS3动画滚动marquee */
.marquee-view .marquee {
animation: move 15s linear infinite;
}
@keyframes move {
0% {
}
100% {
transform: translateY(-50%);
}
}
/* 3.鼠标经过marquee 就停止动画 */
.marquee-view .marquee:hover {
animation-play-state: paused;
}
点位区域(point)-布局
index.html
在监控区域下方添加
<!-- 点位分布统计模块制作 -->
<div class="point panel">
<div class="inner">
<h3>点位分布统计</h3>
<div class="chart">
<div class