本篇文章主要讲我在开发过程中使用到的Echarts使用案例,具体的更多特性可以参考Echarts官网。(注:因为项目机密的原因,本文的代码对敏感内容进行了修改)
Echarts官网:https://echarts.baidu.com/
Echarts是一个开源的数据可视化工具,一个纯Javascript的图表库,用来制图特别方便。
在使用Echarts的时候,都需要导包,在中导入import echarts from ‘echarts’:
- Echarts的折线图
<b-card title="总设备折线图" class="mb-2">
<b-table hover show-empty :items="devicehistory.list" :fields="devicehistory.fields" >
</b-table>
然后在vue的 < s c r i p t > < / s c r i p t > <script></script> <script></script>中定义devicehistory这个集合变量:
devicehistory: {
list: [],
fields: {
month: {
label: '月份',
sortable: true,
'class': 'text-left'
},
totalDevice: {
label: '总设备数',
sortable: true,
'class': 'text-left'
},
onlineDevice: {
label: '线上设备数',
sortable: true,
'class': 'text-left'
},
braceDevice: {
label: '支撑设备数',
sortable: true,
'class': 'text-left'
},
bufferDevice: {
label: 'buffer设备数',
sortable: true,
'class': 'text-left'
},
coldDevice: {
label: '冷备设备数',
sortable: true,
'class': 'text-left'
},
overDevice: {
label: '过保设备数',
sortable: true,
'class': 'text-left'
},
}
},
要设置两个参数,一个是list集合,用来存放每一行fileds的数据的。Fields里面存放每一列要显示的列表,每一个字段的属性可以自己设置,这里的属性有三个(也可以是多个)label是列名,sortable表示是否点击根据列明排序,class为对齐。然后我们就可以自定义初始化这个devicehistory集合的函数,可以把这个函数放在vue的初始化函数中。
mounted: function () {
this. getDevicehistory ()
},
在这个函数中通过得到后台的数据,把数据放入devicehistory的list当中。函数的定义与实现是在nodejs的methods:{}当中。
Methods:{
getDeviceHistory:function(){
this.$http.get(`${this.$config.API}/_api/echarts/getAllNewData`,{params:{cnamedb:this.cnamedb}}).then((response) => {
let md = response.body
this.devicehistory.list = []
if(md.length>0){
for(var i=0;i<md.length;i++){
var obj = {"month":'',"totalDevice":0,"onlineDevice":0,"braceDevice":0,"bufferDevice":0,"coldDevice":0,"overDevice":0}
obj.month = md[i].month
obj.onlineDevice = md[i].online
obj.braceDevice = md[i].brace
obj.bufferDevice = md[i].buffe
obj.coldDevice = md[i].cold
obj.overDevice = md[i].overInsurance
obj.totalDevice = md[i].online + md[i].brace + md[i].buffe + md[i].cold + md[i].overInsurance
this.devicehistory.list.push(obj)
}
}
}).catch(function (response) {
console.log(response)
})
},
}
其中,this.$http.get()有两个参数,第一个是我们要传入的地址,第二个参数params是我们要传入后台的参数。在后台代码incomecenter.js中,用nodejs来编写的,代码如下:
const router = require('koa-router')()
const db = require('../../common/Db')
router.get('/getAllNewData', async(ctx, next) => {
var cnamedb = ctx.query.cnamedb
var sql = `SELECT * FROM databus.totalCount`
ret = await db.databus.query(sql)
ctx.body = ret;
})
通过ctx.query的方式来获取前面传入的param,通过ctx.body来把执行结果返回。
使用router的get或者post方法去接收http请求并调用对应的函数。db是一个实例数组,在暴露出来的const db = require(’…/…/common/Db’)中我们可以发现:
在db中我们查看到他是通过连接池来获取到了一个连接connection。现在我们来讲一下nodejs中使用连接池创建连接的方法:
var mysql = require('mysql')
var pool = mysql.createpool({ #下面的那些参数都是事先定义好了的
"host":host,
"user":username,
"port":port,
"password":password,
"database":dbname, #打开哪一个数据库
"charset":"utf8"
}) #创建mysql的连接池
pool.getConnection(function(err,connection){
if(err){
console.log('连接失败')
}
else{ #获取到connection
connection.query('sql',function(err,data){
if(err){
console.log(err)
}else{
console.log(data)
connection.end()
}
})
}
})
在nodejs中,提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。在nodejs中,又两种方式对外暴露方法,一种是exports,另一种是model.exports。这两个的区别如下:
①module.exports 初始值为一个空对象 {}
②exports 是指向的 module.exports 的引用
③require() 返回的是 module.exports 而不是 exports
一般而言,导出对象用model.exports,导入多个方法用exports:
var outputVal = 0; //输出值
var increment = 1; //增量
/* 设置输出值 */
var handle;
handle = {
str:"hello_world",
fn: function () {
wx.showToast({
title: 'hello_world',
})
}
}
function seOutputVal (val) {
outputVal = val;
}
exports.seOutputVal = seOutputVal;
module.exports = handle;
现在继续回到getDeviceHistory方法的代码,我们可以通过response.body来获取后台返回的结果,我们通过console.log(md)来看返回的结果是什么样子:
上面对数据库返回的字段名进行的屏蔽。
也就是说,返回的结果是一个数组字典,通过md[i]的形式就可以获取到里面的值,传入我们的list当中,而想传入到list当中,就要在for循环中创建一个存放fields的字典obj,需要注意的是,这个obj的字段名一定要和定义的devicehistory中的fileds的相同。最终实现效果如下:
- 折线图 echarts中的type为line
在 < t e m p l a t e > <template> <template>里面的代码如下:
<div class="hello">
<div id="barChartByTotalDevice" :style="{width: '100%',height:'480px'}"></div>
</div>
这里的style就是我们这个折线图的大小。接下来我们要做的,就是根据这个id,来为他初始化echarts的折线图。所以我们现在需要设计一个函数getTotalDeviceDrawBar,来实现这个初始化。
getTotalDeviceDrawBar:function(){
var xdata = []
var ydata1 = []
var ydata2 = []
var ydata3 = []
var ydata4 = []
var ydata5 = []
for(var i=0;i<this.SumOfDevice.list.length;i++){
var obj = this.SumOfDevice.list[i]
xdata.push(obj.month)
ydata1.push(obj.online)
ydata2.push(obj.brace)
ydata3.push(obj.buffe)
ydata4.push(obj.cold)
ydata5.push(obj.overInsurance)
}
var ydata = []
ydata.push(ydata1)
ydata.push(ydata2)
ydata.push(ydata3)
ydata.push(ydata4)
ydata.push(ydata5)
var series = []
var seriesname = ['线上设备数','支撑设备数','Buffe模块设备数','冷备模块设备数','过保设备数']
for(var i=0;i<5;i++){
var obj = {
name:seriesname[i],
type:'line',
data:ydata[i],
markPoint : {
data : [
{type : 'max', name: '最大值'},
{type : 'min', name: '最小值'}
]
},
markLine : {
data : [
{type : 'average', name: '平均值'}
]
}
}
series.push(obj)
}
let barChart = echarts.init(document.getElementById('barChartByTotalDevice'))
var option = {
title : {
text: '总设备数折线图',
},
tooltip : {
trigger: 'axis'
},
legend: {
data:['线上设备数','支撑设备数','Buffe模块设备数','冷备模块设备数','过保设备数']
},
toolbox: {
show : true,
},
calculable : true,
xAxis : [
{
type : 'category',
data : xdata
}
],
yAxis : [
{
type : 'value'
}
],
series : series
}
barChart.setOption(option)
},
所以,通过let barChart = echarts.init(document.getElementById(‘barChartByTotalDevice’))来得到这个id,通过通过这个idbarChart.setOption(option) 来完成初始化,这个传入的option就是我们需要设置的折线图初始化参数。
一般而言,这个option里面的属性有很多,可以去官网查,我们这里只用到了:
(1) tooltip提示框组件,trigger出发类型axis为坐标轴触发查看详情。
(2) legend图例的字段名字,data来设置图例的数据数组。
(3) toolbox设置工具栏。这里其实没用到,设置了的话可以去官网查对应的属性实现柱状图转换,数据视图转换等需求。
(4) xAxis横坐标设置,type为类型选择category为类目轴,适用于离散的类目数据data横坐标数据,传入的是一个数组。
(5) yAxis纵坐标设置,type为value表示是数据轴,适用于连续数据。这里没有写data,则默认会去从 series.data中取获值,如果 series.data中没值则什么都没有。
(6) series:其实是一个系列列表series[i],也就是数组字典。每个系列通过 type 决定自己的图表类型。可以看到这里的series是单独拿出去设置了的,毕竟有五个值。在series中,type表示系列类型,line是折线图,pie是饼图,bar是柱状图。name要和option中的legend一致。series-line.markPoint表示图表标注,通过data来设置做大最小值,series-line.markLine设置图表标线,用data来设置平均值。
而这里的xdata和ydata是通过上面的读取后台数据放入this.SumOfDevice.list中了的,而sumofDevice可以在vue初始化调用函数中设置函数读取数据即可。所以最终的实现效果如下:
3. 饼图 series[i]-pie
模式和上面差不多,在template的代码如下:
<div class="col-sm-6 col-md-6">
<div id="prdlevel1" :style="{width: '100%',height:'480px'}"></div>
</div>
然后再在函数中根据这个id设置option,然后setOption(option)即可,和折线图主要的不同就是series的不同,我们需要去官网找到series[i]-pie的一些列series的设置即可。itemStyle指的是图像的相识,name名字,data数据,center表示图饼圆心坐标,默认是[ default: [‘50%’, ‘50%’] ],第一项横坐标,第二项纵坐标。
drawPie(text,subtext,barId,name,data,legend){
var pieChart = echarts.init(document.getElementById(barId))
var option = {
title : {
text: text,
subtext: subtext,
x:'center'
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient: 'vertical',
left: 'left',
data: legend
},
series : [
{
name: name,
type: 'pie',
radius : '55%',
center: ['50%', '60%'],
data:data,
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
pieChart.setOption(option)
},
最终实现效果如下: