1、在折线图/柱状图中,如何自定义悬浮提示框tooltip之formatter?
项目需求:在折线图上,鼠标悬停后,提示框除了展示横纵坐标相关数据外,还需额外展示其余相关数据, 如下图所示。
解决思路:
1、首先,搞清楚tooltip里的数据配置项options的哪儿获取:传递到tooltip.formatter函数里的参数params是从series里面的data获取。( 解释series: 系列列表,每个系列通过 type 决定自己的图表类型。其数据格式为[{},{},...],每个{}存贮对每条曲线的配置项。)因此,tooltip.formatter方法中的参数params格式也是对象数据。
2、其次,当鼠标悬浮于图表中某个坐标交叉点后,便会触发options.tooltip.formatter()方法。
文档中对formatter的说明:
标签内容格式器,支持字符串模板和回调函数两种形式,字符串模板与回调函数返回的字符串均支持用 \n 换行。
字符串模板 模板变量有:
{a}:系列名。
{b}:数据名。
{c}:数据值。
{@xxx}:数据中名为'xxx'的维度的值,如{@product}表示名为'product'的维度的值。 {@[n]}:数据中维度n的值,如{@[3]}表示维度 3 的值,从 0 开始计数。
示例: formatter: '{b}: {@score}'
解决方案:通过自定义配置option.tooltip.formatter()方法。
后端数据格式:
avgFailCountList: [
{time: "2020-04-09", failCount: 490720, failNum: 42867, avgFailCount: 11},
{time: "2020-04-10", failCount: 2652729, failNum: 79549, avgFailCount: 27},
{time: "2020-04-11", failCount: 2327734, failNum: 137805, avgFailCount: 16},
{time: "2020-04-12", failCount: 1107100, failNum: 93675, avgFailCount: 11},
{time: "2020-04-13", failCount: 214373, failNum: 11233, avgFailCount: 19},
{time: "2020-04-14", failCount: 262099, failNum: 22946, avgFailCount: 11},
{time: "2020-04-15", failCount: 279015, failNum: 30705, avgFailCount: 9}
]
配置项具体操作如下:
optionsHandle(res) { // res 为后端返回数据
options.tooltip.formatter = function(params) {
let item = params[0]
item.data = res
let _avgFailCount = ''
let _failNum = ''
let _failCount = ''
for(let i = 0; i < item.data.length; i++) {
// 分别将item.name(横坐标值)和item.data[i].time作比较,并分别赋给自定义的变量,便于return 时返回鼠标悬浮于该点的数据值
if(item.name == item.data[i].time) {
_avgFailCount = item.data[i].avgFailCount
_failNum = item.data[i].failNum
_failCount = item.data[i].failCount
}
}
return `日期:${item.name} <br/>
拉流失败次数:${_failCount} <br/>
拉流失败人数:${_failNum} <br/>
${item.seriesName}:${_avgFailCount}`
}
}
本例中,打印参数params如下:
2、在一个折线图中,需要展示多条曲线,各曲线的X轴数值不同,如何展示?
项目需求:如下图所示的折线图,展示多个用户uid的上行帧率数据,每个用户展示一条曲线。但采集到的用户数据起止时间各不相同,且各个用户的时间间隔也不相同,需要按照正常的时间顺序,使图表正确展示。
解决思路:
1、因为每条线的x轴不同,所以普通的渲染方式无法实现。
2、解决办法是将所有曲线的所有时间点进行聚合并排序(日期的从小到大),并赋值给x轴的配置项options.xAxis.data。
3、设置options.series[i].data(i代表该条曲线)的数据格式 -- [ [x,y],[x,y],... ].如下所示。
后端数据格式:
cpuList: [
[
{time: "2020-04-18 14:44:43", value: "43.33", uid: "2524412"},
{time: "2020-04-18 14:45:13", value: "38.0", uid: "2524412"}
]
[
{time: "2020-04-18 14:24:49", value: "26.91", uid: "2497102"},
{time: "2020-04-18 14:25:19", value: "57.66", uid: "2497102"},
{time: "2020-04-18 14:25:49", value: "33.28", uid: "2497102"},
{time: "2020-04-18 14:26:19", value: "37.93", uid: "2497102"},
{time: "2020-04-18 14:26:49", value: "20.49", uid: "2497102"},
...
]
[ {time: "2020-04-18 14:36:54", value: "37.42", uid: "2086662"},
{time: "2020-04-18 14:37:24", value: "46.4", uid: "2086662"},
{time: "2020-04-18 14:37:54", value: "38.47", uid: "2086662"},
{time: "2020-04-18 14:38:24", value: "52.31", uid: "2086662"},
{time: "2020-04-18 14:38:54", value: "46.94", uid: "2086662"},
...
]
[
{time: "2020-04-18 14:37:06", value: "57.4", uid: "3868963"},
{time: "2020-04-18 14:37:36", value: "71.85", uid: "3868963"},
{time: "2020-04-18 14:38:06", value: "29.82", uid: "3868963"},
{time: "2020-04-18 14:38:36", value: "25.02", uid: "3868963"},
{time: "2020-04-18 14:39:06", value: "65.13", uid: "3868963"},
{time: "2020-04-18 14:39:36", value: "68.03", uid: "3868963"},
...
]
]
代码如下:
// 配置项 resData为后端返回数据(上面已举例),resName为y轴名称(yAxis[i].name)
optionsHandle(resData, resName) {
// 配置系列项,即这张图表每条曲线的基础配置
let seriesItem = {
type: 'line',
symbolSize: 6,
smooth: true,
yAxisIndex: 0,
lineStyle: { // 折线样式
width: 2
},
areaStyle: { // 填充区域
opacity: 0.1
},
symbol: 'circle',
markPoint: {
symbol: 'circle',
symbolSize: 9,
itemStyle: {
color: '#016072'
},
data: [
{
symbol: 'pin',
symbolSize: 25,
itemStyle: {
color: '#555'
}
}
]
}
}
// 根据后端返回数据的条数(有几条折线),动态配置有多少系列列表
for(let i = 0; i < resData.length; i++) {
this.options.series.push(seriesItem)
}
let options = JSON.parse(JSON.stringify(this.options)) // this.options为此项目options的基础配置
let clientTime = [] // 定义横坐标时间数组
// 遍历后端返回的所有项(包括每条曲线的所有time),进行聚合
for(let i = 0; i < resData.length; i++) {
let timeSet = resData[i].map(item => item.time)
clientTime = [...clientTime, ...timeSet]
}
// 聚合所有time 并去重,排序
clientTime = [...new Set(clientTime)]
// 此函数功能:对时间排序
function sortUpDate(a, b) {
return Date.parse(a) - Date.parse(b)
}
clientTime.sort(sortUpDate) // 日期排序
// 对图表x轴赋值,不显示 年 (eg: 04-18 12:23:09)
options.xAxis.data = clientTime.map(item => item.substr(5))
options.grid.left = '6%'
options.yAxis[0].name = resName
// 配置图表右上方的标记属性
for(let i = 0; i < resData.length; i++) {
options.legend.data.push(resData[i][0].uid)
options.series[i].name = resData[i][0].uid
}
// 在options配置项里 配置每条曲线的数据 格式为
// options.series[i].data = [['04-18 12:23:09', 232],['04-18 14:23:09', 1232],...]
let itemArr = []
for(let i = 0; i < resData.length; i++) {
let res = []
resData[i].map(item => {
itemArr = [item.time.substr(5), item.value]
res.push(itemArr)
})
options.series[i].data = res
}
return options
}