上周重构项目数据统计部分写了几篇echarts相关的文章,重构的后台前端框架改用Vue,关于Vue中引用Echarts及可能遇到的问题的文章如下所示:
其中提到大学的时候echarts教程较少,想要做一些理想效果比较麻烦,正好记得大三的时候写了一个,基于Echarts+Three.js+百度地图的数据可视化系统,当时这个系统参加了计算机设计大赛,是拿了安徽省一等奖,全国二等奖,里面有写了几个关于Echarts的样式,当时的技术还比较菜,系统里面的代码仅供参考。
系统介绍视频【比赛演示视频】
基于Echarts+百度地图+Three.js的数据可视化系统
下面就介绍下系统用到的Echarts+百度地图+Three.js:
一、Echarts开发介绍
关于echarts图表部分以下面这个图表进行介绍
这个图表使用的是带有涟漪特效动画的散点(气泡)图,利用动画特效可以将某些想要突出的数据进行视觉突出,在图表配置文件series中将type值设置成effectScatter就可以了。
上面效果的话,首先是把图表自带的一些样式给隐藏,主要在xAxis和yAxis更改一些属性,然后在series设置气泡的样式。关于鼠标在图表内移动展示的提示部分,主要是修改默认的提示框组件样式,将formatter方法返回的内容自定义成自己开发的组件样式,提示框组件部分如下所示:
// 该部分只是布局代码,样式写在上面的样式内
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
formatter: function (params) { // 当鼠标在图表的区域,设置提示栏的CSS样式
return '消防员姓名 ' + params[0].name + ' 所在楼层 ' + params[0].value + ' 当前温度 30 当前气压 20 状态 移动
';
}
}
// 其中params参数里面包含了当前位置X轴、Y轴的数据
该图表代码如下所示【系统源码下载:h5-simple-visualization】:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" name="viewport"/>
<title></title>
<!-- 引入echarts -->
<script src="../libs/js/echarts.js"></script>
<style type="text/css">
html, body {
overflow: hidden;
height: 100%;
background: linear-gradient(#104BAA, #000000);
margin: 0;
padding: 0;
}
p, ul, li {
margin: 0;
padding: 0;
list-style-type: none;
}
.index {
margin-top: 135px;
}
.index .tit {
width: 100%;
height: 50px;
font-size: 25px;
text-align: center;
font-family: Arial, 华文新魏;
font-weight: bold;
line-height: 50px;
border-radius: 20px;
color: #00FFCC;
border-bottom: 1px solid #0099ff;
box-shadow: 0 0 15px 1px #20558b;
}
.index .box {
width: 96%;
height: 1200px;
margin-left: 2%;
margin-top: 120px;
border: 1px solid #0099ff;
box-shadow: 0 0 15px 1px #20558b;
border-radius: 25px;
}
.index .echart {
width: 96%;
height: 575px;
margin-top: 20px;
margin-left: 2%;
padding-top: 20px;
background-color: rgba(0, 24, 106, 0.5);
border: 1px solid #20558b;
box-shadow: 0 0 15px 1px #20558b;
position: relative;
}
.index #main {
width: 100%;
height: 600px;
}
.echarts {
width: 200px;
height: 250px;
color: #00FFCC;
font-size: 20px;
font-family: Arial, 华文新魏;
background-color: rgba(0, 24, 106, 0.5);
border: 1px solid #20558b;
box-shadow: 0 0 15px 1px #20558b;
position: relative;
}
.moddle {
width: 96%;
height: 500px;
margin-top: 10px;
margin-left: 2%;
background-color: rgba(0, 24, 106, 0.5);
border: 1px solid #20558b;
box-shadow: 0 0 15px 1px #20558b;
position: relative;
}
.moddle .ifra {
width: 96%;
height: 470px;
margin-left: 2%;
margin-top: 12px;
}
table {
width: 100%;
height: 250px;
text-align: center;
padding-top: 10px;
}
table img {
width: 100%;
height: 80px;
}
.bj-1 {
position: absolute;
left: -1px;
top: -1px;
}
.bj-2 {
position: absolute;
right: -1px;
top: -1px;
}
.bj-3 {
position: absolute;
right: -1px;
bottom: -1px;
}
.bj-4 {
position: absolute;
left: -1px;
bottom: -1px;
}
</style>
</head>
<body>
<div class="index">
<div class="box">
<div class="tit">
消防员信息实时监控
</div>
<div class="moddle">
<iframe class="ifra" src="../libs/model/showModel.html">
</iframe>
<img alt="" class="bj-1" src="../libs/img/bj-1.png">
<img alt="" class="bj-2" src="../libs/img/bj-2.png">
<img alt="" class="bj-3" src="../libs/img/bj-3.png">
<img alt="" class="bj-4" src="../libs/img/bj-4.png">
</div>
<div class="echart">
<div id="main">
</div>
<img alt="" class="bj-1" src="../libs/img/bj-1.png">
<img alt="" class="bj-2" src="../libs/img/bj-2.png">
<img alt="" class="bj-3" src="../libs/img/bj-3.png">
<img alt="" class="bj-4" src="../libs/img/bj-4.png">
</div>
</div>
</div>
</body>
</html>
<script>
// 获取图表的ID值,并设置图表的主题风格
let myChart = echarts.init(document.getElementById('main'), 'walden');
let option = {
title: {
text: '所在楼层/层',
left: '5%',
textStyle: {
color: '#00FFCC',
fontFamily: '华文新魏',
fontWeight: 'bold',
fontSize: '25',
align: 'center'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
formatter: function (params) { // 当鼠标在图表的区域,设置提示栏的CSS样式
return '消防员姓名 ' + params[0].name + ' 所在楼层 ' + params[0].value + ' 当前温度 30 当前气压 20 状态 移动
';
}
},
toolbox: {
show: true,
right: '100',
itemGap: 20,
itemSize: '20',
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {
readOnly: false
},
magicType: {
type: ['pictorialBar', 'bar']
},
restore: {},
saveAsImage: {}
},
iconStyle: {
borderColor: '#00FFCC'
}
},
xAxis: {
data: ['消1号', '消2号', '消3号', '消4号', '消5号'],
axisTick: {
show: true
},
axisLine: {
show: false
},
axisLabel: {
textStyle: {
color: '#00FFCC',
fontFamily: '华文新魏',
fontWeight: 'bold',
fontSize: '20',
}
}
},
yAxis: {
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: false
},
axisLabel: {
show: true,
textStyle: {
color: '#00FFCC',
fontFamily: '华文新魏',
fontWeight: 'bold',
fontSize: '20',
}
}
},
color: ['#ffffff'],
series: [{
name: '海拔高度',
type: 'effectScatter',
rippleEffect: {
brushType: 'stroke'
},
symbolSize: 25,
hoverAnimation: true,
barCategoryGap: '-130%',
symbol: 'circle',
itemStyle: {
normal: {
color: '#FF00FF'
},
emphasis: {
color: '#FF00FF'
}
},
data: [5, 0, 1, 5, 3],
z: 10
}],
};
myChart.setOption(option);
// 设置点击跳转方法,并传送图表X属性的值
myChart.on('click', function (params) {
if (params.name == '') {
window.open('new_data.html?a=' + encodeURIComponent(params.name) + '');
}
});
</script>
二、百度地图开发介绍
系统使用百度地图主要是展示在地图上添加一些覆盖物,然后点击覆盖物到其详情页介绍,下面介绍接入流程:
因为这里用的是百度地图,首先的话要去百度地图开发者中心注册成为开发者,然后再控制台应用管理新建一个应用,应用类型选择浏览器端,白名单填写*即可,然后就能拿到应用的key,根据key的话就能调用百度地图。
因为我这个是两年前的系统,用到的地图代码和现在的不同,首先new的地图实例都改变了,具体的可以看下最新的文档。
主要就介绍下面几个方法:
百度地图代码如下所示【项目源码下载:h5-simple-visualization】:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title></title>
<!-- 引入百度地图,这里的key填写自己开发者创建应用的key -->
<script src="http://api.map.baidu.com/api?v=2.0&ak=" type="text/javascript"></script>
<!-- 加载鼠标绘制工具 -->
<script src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js" type="text/javascript"></script>
<link href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" rel="stylesheet"/>
<!-- 加载检索信息窗口 -->
<script src="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.js" type="text/javascript"></script>
<link href="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.css" rel="stylesheet"/>
</head>
<body>
<div class="v_box">
<div class="v_map" id="map" style="width: 100%;height: 500px;">
</div>
</div>
</body>
<script type="text/javascript">
// 初始化地图
let map;
initMap();
// 创建和初始化地图函数:
function initMap() {
createMap(); //创建地图
setMapEvent(); //设置地图事件
addMapControl(); //向地图添加控件
addMapOverlay(); //向地图添加覆盖物
styleMap(); //地图个性化模板
}
function createMap() {
map = new BMap.Map("map");
map.centerAndZoom(new BMap.Point(118.339637, 32.305602), 15);
map.addControl(new BMap.MapTypeControl({
mapTypes: [
BMAP_NORMAL_MAP,
BMAP_HYBRID_MAP
]
}));
// 设置地图显示的城市 此项是必须设置的
map.setCurrentCity("滁州");
map.enableScrollWheelZoom(true);
//添加城市列表
map.enableInertialDragging();
map.enableContinuousZoom();
let size = new BMap.Size(10, 10);
map.addControl(new BMap.CityListControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
offset: size,
}));
}
// 添加地图类型和缩略图
function add_control() {
map.addControl(mapType1); // 2D图,卫星图
map.addControl(mapType2); // 左上角,默认地图控件
map.addControl(overView); // 添加默认缩略地图控件
map.addControl(overViewOpen); // 右下角,打开
}
function setMapEvent() {
map.enableScrollWheelZoom();
map.enableKeyboard();
map.enableDragging();
map.enableDoubleClickZoom()
}
function addClickHandler(target, window) {
target.addEventListener("click", function () {
});
}
function addMapOverlay() {
let data_info = [[118.34264, 32.30297, "滁州市琅琊区消防支队"],
[118.325967, 32.3142, "滁州市琅琊区消防支队"],
[118.357013, 32.291738, "滁州市琅琊区消防支队"],
[118.328842, 32.296133, "滁州市琅琊区消防支队"],
[118.371961, 32.312735, "滁州市琅琊区消防支队"],
[118.351264, 32.325429, "滁州市琅琊区消防支队"]
];
let opts = {
width: 250, // 信息窗口宽度
height: 80, // 信息窗口高度
title: "", // 信息窗口标题
enableMessage: true //设置允许信息窗发送短息
};
for (let i = 0; i < data_info.length; i++) {
let myIcon = new BMap.Icon("../libs/img/x_1.png", new BMap.Size(50, 50), {
offset: new BMap.Size(10, 25)// 设置图片偏移
});
let marker = new BMap.Marker(new BMap.Point(data_info[i][0], data_info[i][1]), {icon: myIcon}); // 创建标注
marker.setAnimation(BMAP_ANIMATION_BOUNCE);
let content = data_info[i][2];
map.addOverlay(marker); // 将标注添加到地图中
addClickHandler(content, marker);
marker.addEventListener('dbclick', function () {
window.location.href = './detail.html';
});
}
function addClickHandler(content, marker) {
marker.addEventListener("click", function (e) {
openInfo(content, e)
}
);
}
function openInfo(content, e) {
let p = e.target;
let point = new BMap.Point(p.getPosition().lng, p.getPosition().lat);
let infoWindow = new BMap.InfoWindow(content, opts); // 创建信息窗口对象
map.openInfoWindow(infoWindow, point); // 开启信息窗口
}
}
// 向地图添加控件
function addMapControl() {
let navControl = new BMap.NavigationControl({
anchor: BMAP_ANCHOR_BOTTOM_RIGHT,
type: BMAP_NAVIGATION_CONTROL_LARGE
});
map.addControl(navControl);
}
// 个性化地图
function styleMap() {
let myStyleJson = [
{
"featureType": "road",
"elementType": "geometry.stroke",
"stylers": {
"color": "#ff0000"
}
}];
map.setMapStyle({styleJson: myStyleJson});
// 这里放自己再样式生成器生成的json
map.setMapStyle({
styleJson: []
});
}
</script>
</html>
三、Three.js开发介绍
系统关于展示模型的部分,使用的是three.js技术,里面使用iframe将这个模型文件引入进来。这个部分比较麻烦些,因为不会自己建模,所以从网上一个模型网站下载了这个模型,然后使用3dmax将模型转成mtl和obj类型的文件,在PrepDataFile内设置下上述两个文件就行。
该部分three.js部分代码使用了学长在网上找的代码,消防车模型代码就是在系统里面建筑部分代码基础上修改的,这里代码太长了可以去项目看下libs/model/max_1.html文件。
three.js代码如下所示【项目源码下载:h5-simple-visualization】:
// 这里代码大概在433行,可以看下libs/model/max_1.html文件
var prepData = new THREE.OBJLoader2.WWOBJLoader2.PrepDataFile(
'1',
'',
'1.obj', // 在这里设置自己的模型文件,就可以将模型引进来
'',
'1.mtl' // 在这里设置自己的模型文件,就可以将模型引进来
);
app.loadFiles(prepData);
下周的话准备出一篇《让CSS3中Transform属性带你一文实现炫酷的转盘抽奖效果》博文,解析转盘抽奖系统的前后端开发过程。