echarts统计图多图表关联
先展示最终效果图,如图,折线图上有一个时间轴,展示对应时间发生了什么,鼠标悬浮展示时间轴事件(当时百度找各种方法就想先看到最终效果是不是我想要的,但还是找不到~~)
思路
首先要解决的是指示器能够关联上面的时间轴,能够戳出自身的y轴高度,但是单图表百度了一圈也没有相关的方法,而且tooltip还要展示时间轴的信息,最后回到官网看到了此示例受到启发,多图表可以通过**‘gridIndex’**这个字段进行关联,并且tooltip会返回所有关联图表的信息
代码
这边使用vue,父子组件传值,想把图表做成可通用的,但是目前还没完全通用,我先趁热记录下来,优化可以顺着思路水到渠成
// 父组件部分
// html
<LineChartDark :echarts-data="echartsData" />
// 传参示例
echartsData: {
xList: ['10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30'],
series: [{
name: '曝光人数',
color: '#4ACAB0',
yAxisIndex: 1,
yList: [1000, 12000, 56000, 87000, 12000, 64550, 1000, 12000, 56000, 87000, 12000, 65550]
}, {
name: '订单增量',
color: '#4A52CA',
yAxisIndex: 1,
yList: [12000, 56000, 87000, 12000, 64550, 1000, 12000, 56000, 87000, 12000, 65550, 1000]
}, {
name: '点击率',
color: '#CAA04A',
yAxisIndex: 2,
yList: [0.12, 0.56, 0.87, 0.12, 0.154, 0.1, 0.12, 0.56, 0.87, 0.12, 0.64, 0.1]
}, {
name: '转化率',
color: '#CA4AB1',
yAxisIndex: 2,
yList: [0.12, 0.16, 0.87, 0.12, 0.154, 0.1, 0.12, 0.56, 0.87, 0.12, 0.64, 0.1]
}]
}
// 子组件部分
// html
<div ref="myChart" style="height: 400px;" />
// js
// 这里引入处理过大数据的方法,效果如上图左y轴的格式化
import { f_number } from '@/filters/modules/tools.js'
export default {
props: {
echartsData: {
type: Object,
default: () => {}
}
},
data() {
return {
option: {
tooltip: {
backgroundColor: '#000000CC',
padding: [10, 12],
trigger: 'axis',
axisPointer: {
type: 'line',
lineStyle: {
color: '#1a4894',
type: 'dashed'
}
},
formatter: function(val) {
const xval = val[0].name // x轴名称
let text = `${xval}<br/>`
val.forEach(item => { // 按照自己的需求格式化tooltip内容
if (item.seriesName === 'indicator' && item.data.label) {
text += `${item.marker}${item.data.label} <br/>`
} else if (item.seriesName !== 'indicator') {
let yval = f_number(item.value)
// 我的场景左y轴单位是人数,不会大于0且小于1,右y轴单位是百分比不会大于1或小于0,所以可以这样判断组成数据
if (yval > 0 && yval < 1) {
yval = (yval * 100).toFixed(0) + '%'
}
text += `${item.marker} ${item.seriesName}:${yval} <br/>`
}
})
return text
}
},
legend: {
left: '0',
top: '20px',
itemHeight: 10,
itemWidth: 10,
itemGap: 20,
textStyle: {
color: '#5c5f75',
fontSize: 12,
rich: {
a: {
padding: [-3, 0, 0, 0]
}
}
},
formatter: name => '{a|' + name + '}',
data: []
},
// 这里是一个关键点,grid决定图表位置,所以我将时间轴的位置设置地较大且涵盖下方的折线图,grid为数组时下标对应xAxis和yAxis的gridIndex(默认为0,为0时可不写)值
grid: [{
left: '4.5%',
right: '4.5%',
top: '18%',
bottom: '5%',
containLabel: false // 这个字段决定y轴边界不变,这样才能将两个图表等宽,因为时间轴不展示y轴的也没有示数
}, {
left: '4.5%',
right: '4.5%',
top: '30%',
bottom: '5%',
containLabel: false
}],
axisPointer: { // 指示器联动
link: { xAxisIndex: 'all' }
},
xAxis: [{
// 在这里配置时间轴x轴相关参数,数据和下方折线图应是一样的,注意要让所有的刻度,示数,网格线都不展示
data: [],
gridIndex: 0,
boundaryGap: false,
axisTick: {
// 刻度线
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: false
},
splitLine: {
show: false
},
type: 'category'
}, {
data: [],
gridIndex: 1,
boundaryGap: false,
axisTick: {
// 刻度线
show: false
},
axisLine: {
lineStyle: {
color: '#2e334e'
}
},
axisLabel: {
color: '#54586e'
},
splitLine: {
show: false
},
type: 'category'
}],
yAxis: [{
// 在这里配置时间轴y轴相关参数,注意要让所有的刻度,示数,网格线都不展示,我们仅展示折线就够了
type: 'value',
gridIndex: 0,
axisTick: {
show: false
},
axisLine: {
show: false
},
min: 0,
max: 10, // 这里设置时间轴表的最大值,随意大于min就好
splitNumber: 1,
axisLabel: {
show: false
},
splitLine: {
show: false
}
}, {
type: 'value',
gridIndex: 1,
axisTick: {
// 刻度线
show: false
},
splitNumber: 5,
axisLine: {
show: false
},
axisLabel: {
color: '#737688',
formatter: function(v) {
return f_number(v)
}
},
splitLine: {
show: true,
lineStyle: {
color: '#2e334e',
type: 'dashed'
}
}
}, {
type: 'value',
gridIndex: 1,
axisTick: {
// 刻度线
show: false
},
min: 0,
max: 1,
splitNumber: 5,
axisLine: {
show: false
},
axisLabel: {
color: '#737688',
formatter: function(v) {
return (v * 100).toFixed(0) + '%'
}
},
splitLine: {
show: false,
lineStyle: {
color: '#2e334e'
}
}
}],
series: [{
// 数据组名字,用于tooltip判断拼接提示文字
name: 'indicator',
data: [{ // 这里设置时间轴的数据,都是最大值,这样可以在折线图顶部展示,数据可以由父组件传值,子组件整理好就行,是个可优化的地方,需要展示圆点(大事记)的地方就设置拐点,不展示就隐藏拐点
value: 10,
label: '商品上架',
symbolSize: 10,
symbol: 'circle',
itemStyle: {
normal: {
color: '#ff6611',
borderColor: '#ff6611'
}
}
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
symbolSize: 0
}, {
value: 10,
label: '商品下架',
symbolSize: 10,
symbol: 'circle',
itemStyle: {
normal: {
color: '#999999',
borderColor: '#999999'
}
}
}],
type: 'line',
// 设置关联前面配置的第一个x轴与第一个y轴
xAxisIndex: 0,
yAxisIndex: 0,
lineStyle: {
color: '#3d4159',
width: 1
}
}]
}
}
},
mounted() {
// 整理父组件传来的值并渲染
this.option.xAxis[0].data = this.option.xAxis[1].data = this.echartsData.xList
this.echartsData.series.forEach(item => {
this.option.legend.data.push({
icon: 'circle',
name: item.name
})
this.option.series.push({
name: item.name,
data: item.yList,
type: 'line',
xAxisIndex: 1,
yAxisIndex: item.yAxisIndex,
showSymbol: false,
smooth: true,
lineStyle: {
color: item.color,
width: 3
},
itemStyle: {
normal: {
color: item.color
},
emphasis: {
color: item.color, // 颜色
shadowBlur: 4, // 图形的阴影大小
shadowColor: item.color + '80' // 图形的阴影颜色
}
}
})
})
console.log('>>>', this.option)
// 全局方法的渲染
this.$initEcharts(this.$refs.myChart, this.option)
// 其实就是这样
// let myChart = echarts.init(this.$refs.myChart);
// window.onresize = myChart.resize;
// myChart.setOption(this.option);
}
}
哈哈哈
合理的事情总会有解决方案的,有时候换个思路就能豁然开朗