在实际开发中,当遇到两个图表联动,主表为柱状图,副表为线性图;当选中主表某地区时,需要将此地区进行高亮处理,并更新副表数据;此时,主表中须使用到splitArea属性,给选中区域添加背景色,表示该区域已被选中。效果如下图:
如图,我们此次完成是指定区域的电量发电量以及使用率等数据展示,并且当主表切换地区时,更新区域的高亮样式,以及实时更新副表中使用率数据。
一、测试数据
以下为本次图表效果测试数据,代码如下:
[
{
"name": "北京",
"online": [
{
"name": 1,
"value": 70
},
{
"name": 2,
"value": 20
},
{
"name": 3,
"value": 24
},
{
"name": 4,
"value": 13
},
{
"name": 5,
"value": 14
},
{
"name": 6,
"value": 12
},
{
"name": 7,
"value": 14
},
{
"name": 8,
"value": 68
},
{
"name": 9,
"value": 51
},
{
"name": 10,
"value": 24
},
{
"name": 11,
"value": 70
},
{
"name": 12,
"value": 76
}
],
"onlineValue": 4560,
"electric": [
{
"name": 1,
"value": 93
},
{
"name": 2,
"value": 13
},
{
"name": 3,
"value": 20
},
{
"name": 4,
"value": 27
},
{
"name": 5,
"value": 22
},
{
"name": 6,
"value": 11
},
{
"name": 7,
"value": 26
},
{
"name": 8,
"value": 63
},
{
"name": 9,
"value": 54
},
{
"name": 10,
"value": 23
},
{
"name": 11,
"value": 85
},
{
"name": 12,
"value": 58
}
],
"electricValue": 4950
},
{
"name": "天津",
"online": [
{
"name": 1,
"value": 58
},
{
"name": 2,
"value": 27
},
{
"name": 3,
"value": 16
},
{
"name": 4,
"value": 14
},
{
"name": 5,
"value": 30
},
{
"name": 6,
"value": 11
},
{
"name": 7,
"value": 19
},
{
"name": 8,
"value": 57
},
{
"name": 9,
"value": 86
},
{
"name": 10,
"value": 21
},
{
"name": 11,
"value": 72
},
{
"name": 12,
"value": 61
}
],
"onlineValue": 4720,
"electric": [
{
"name": 1,
"value": 71
},
{
"name": 2,
"value": 23
},
{
"name": 3,
"value": 15
},
{
"name": 4,
"value": 20
},
{
"name": 5,
"value": 28
},
{
"name": 6,
"value": 20
},
{
"name": 7,
"value": 20
},
{
"name": 8,
"value": 95
},
{
"name": 9,
"value": 85
},
{
"name": 10,
"value": 29
},
{
"name": 11,
"value": 73
},
{
"name": 12,
"value": 80
}
],
"electricValue": 5590
},
{
"name": "上海",
"online": [
{
"name": 1,
"value": 96
},
{
"name": 2,
"value": 20
},
{
"name": 3,
"value": 26
},
{
"name": 4,
"value": 21
},
{
"name": 5,
"value": 20
},
{
"name": 6,
"value": 28
},
{
"name": 7,
"value": 24
},
{
"name": 8,
"value": 51
},
{
"name": 9,
"value": 95
},
{
"name": 10,
"value": 13
},
{
"name": 11,
"value": 68
},
{
"name": 12,
"value": 59
}
],
"onlineValue": 5210,
"electric": [
{
"name": 1,
"value": 98
},
{
"name": 2,
"value": 30
},
{
"name": 3,
"value": 15
},
{
"name": 4,
"value": 29
},
{
"name": 5,
"value": 28
},
{
"name": 6,
"value": 15
},
{
"name": 7,
"value": 25
},
{
"name": 8,
"value": 88
},
{
"name": 9,
"value": 98
},
{
"name": 10,
"value": 29
},
{
"name": 11,
"value": 66
},
{
"name": 12,
"value": 69
}
],
"electricValue": 5900
},
{
"name": "重庆",
"online": [
{
"name": 1,
"value": 77
},
{
"name": 2,
"value": 19
},
{
"name": 3,
"value": 29
},
{
"name": 4,
"value": 30
},
{
"name": 5,
"value": 24
},
{
"name": 6,
"value": 21
},
{
"name": 7,
"value": 25
},
{
"name": 8,
"value": 62
},
{
"name": 9,
"value": 72
},
{
"name": 10,
"value": 19
},
{
"name": 11,
"value": 89
},
{
"name": 12,
"value": 65
}
],
"onlineValue": 5320,
"electric": [
{
"name": 1,
"value": 71
},
{
"name": 2,
"value": 10
},
{
"name": 3,
"value": 28
},
{
"name": 4,
"value": 14
},
{
"name": 5,
"value": 14
},
{
"name": 6,
"value": 22
},
{
"name": 7,
"value": 17
},
{
"name": 8,
"value": 81
},
{
"name": 9,
"value": 71
},
{
"name": 10,
"value": 12
},
{
"name": 11,
"value": 76
},
{
"name": 12,
"value": 72
}
],
"electricValue": 4880
},
{
"name": "南京",
"online": [
{
"name": 1,
"value": 99
},
{
"name": 2,
"value": 12
},
{
"name": 3,
"value": 28
},
{
"name": 4,
"value": 30
},
{
"name": 5,
"value": 13
},
{
"name": 6,
"value": 29
},
{
"name": 7,
"value": 19
},
{
"name": 8,
"value": 70
},
{
"name": 9,
"value": 82
},
{
"name": 10,
"value": 26
},
{
"name": 11,
"value": 50
},
{
"name": 12,
"value": 56
}
],
"onlineValue": 5140,
"electric": [
{
"name": 1,
"value": 75
},
{
"name": 2,
"value": 11
},
{
"name": 3,
"value": 23
},
{
"name": 4,
"value": 25
},
{
"name": 5,
"value": 11
},
{
"name": 6,
"value": 24
},
{
"name": 7,
"value": 13
},
{
"name": 8,
"value": 72
},
{
"name": 9,
"value": 69
},
{
"name": 10,
"value": 28
},
{
"name": 11,
"value": 63
},
{
"name": 12,
"value": 67
}
],
"electricValue": 4810
},
{
"name": "西安",
"online": [
{
"name": 1,
"value": 50
},
{
"name": 2,
"value": 17
},
{
"name": 3,
"value": 17
},
{
"name": 4,
"value": 11
},
{
"name": 5,
"value": 15
},
{
"name": 6,
"value": 15
},
{
"name": 7,
"value": 22
},
{
"name": 8,
"value": 93
},
{
"name": 9,
"value": 92
},
{
"name": 10,
"value": 27
},
{
"name": 11,
"value": 57
},
{
"name": 12,
"value": 89
}
],
"onlineValue": 5050,
"electric": [
{
"name": 1,
"value": 76
},
{
"name": 2,
"value": 19
},
{
"name": 3,
"value": 12
},
{
"name": 4,
"value": 19
},
{
"name": 5,
"value": 14
},
{
"name": 6,
"value": 30
},
{
"name": 7,
"value": 11
},
{
"name": 8,
"value": 53
},
{
"name": 9,
"value": 70
},
{
"name": 10,
"value": 19
},
{
"name": 11,
"value": 74
},
{
"name": 12,
"value": 95
}
],
"electricValue": 4920
}
]
单独存放在一个js文件中,使用时在页面中引入即可。
二、创建页面
首先,在Vue项目中,创建一个模板,在路由器中添加该模板为一个新页面,并通过路由访问该页面。代码如下:
<template>
<div class="chart" ref="chart"></div>
</template>
<script>
import { } from './data/options'
export default {
name: 'SplitBg',
data () {
return {
chartRef: null
}
},
mounted () {
this.initialChart()
},
methods: {
initialChart () {
// 初始化画板
this.chartRef = this.$echart.init(this.$refs['chart'])
},
// 渲染图表
renderChart () {
}
}
}
</script>
<style lang="less" scoped>
.chart{
width: 100%;
height: 100%;
}
</style>
此时图表的画板已创建,但页面没有任何数据信息,这时则需要添加图表配置项等相关数据。
三、创建主副图表
我们先将主副图表创建出来,再慢慢完善配置项,并达到预期效果。
创建options.js文件,将“一、测试数据”也一并保存在该js文件中,通过import导入到页面中。options.js代码如下:
export const chartData = [
{
"name": "北京",
"online": [
{
"name": 1,
"value": 70
},
{
"name": 2,
"value": 20
},
{
"name": 3,
"value": 24
},
{
"name": 4,
"value": 13
},
{
"name": 5,
"value": 14
},
{
"name": 6,
"value": 12
},
{
"name": 7,
"value": 14
},
{
"name": 8,
"value": 68
},
{
"name": 9,
"value": 51
},
{
"name": 10,
"value": 24
},
{
"name": 11,
"value": 70
},
{
"name": 12,
"value": 76
}
],
"onlineValue": 4560,
"electric": [
{
"name": 1,
"value": 93
},
{
"name": 2,
"value": 13
},
{
"name": 3,
"value": 20
},
{
"name": 4,
"value": 27
},
{
"name": 5,
"value": 22
},
{
"name": 6,
"value": 11
},
{
"name": 7,
"value": 26
},
{
"name": 8,
"value": 63
},
{
"name": 9,
"value": 54
},
{
"name": 10,
"value": 23
},
{
"name": 11,
"value": 85
},
{
"name": 12,
"value": 58
}
],
"electricValue": 4950
},
// 略...
]
export const chartOptions = (chartData, selectedIndex) => {
return {}
}
页面代码如下:
<template>
<div class="chart" ref="chart"></div>
</template>
<script>
import { chartData, chartOptions } from './data/options'
export default {
name: 'SplitBg',
data () {
return {
chartRef: null,
selectedIndex: 0
}
},
mounted () {
this.initialChart()
},
methods: {
initialChart () {
// 初始化画板
this.chartRef = this.$echart.init(this.$refs['chart'])
this.renderChart()
},
// 渲染图表
renderChart () {
this.chartRef.setOption(chartOptions(chartData, selectedIndex))
}
}
}
</script>
<style lang="less" scoped>
.chart{
width: 100%;
height: 100%;
}
</style>
3.1 区域划分
先将主副表区域绘制出来,这部分代码也比较简单,配置项如下:
export const chartOptions = (chartData, selectedIndex) => {
return {
grid: [
{
bottom: '55%'
},
{
top: '58%'
}
],
xAxis: [
{
type: 'category',
data: chartData.map((item) => item.name),
gridIndex: 0
},
{
type: 'category',
data: chartData[selectedIndex]['electric'].map((item) => item.name),
gridIndex: 1
}
],
yAxis: [
{
type: 'value',
gridIndex: 0,
name: '单元:kWh'
},
{
type: 'value',
gridIndex: 1,
name: '单位:%'
}
]
}
}
页面效果如下图:
在配置项中,首先是通过grid网格将画板分割成两部分,并且指定xAxis和yAxis中gridIndex索引,将坐标系绘制到对应的网格区域中。
另外,如上图数据结构可见,副表中横坐标则是要通过主表中数据获取,所以在渲染时,默认先取第一项中的电量数量,即selectedIndex默认为0。
3.2 绘制图表
接下来则是在配置项中添加数据,在配置项中增加series即可,并且告诉主副表,各自对应的xAxisIndex和yAxisIndex。柱状图都在坐标系0位置,线性图都在坐标系为1位置。
代码如下:
export const chartOptions = (chartData, selectedIndex) => {
// 电量图公共配置参数
const barOption = {
type: 'bar',
barWidth: 20,
yAxisIndex: 0,
xAxisIndex: 0
}
// 线性图公共配置项
const lineOption = {
type: 'line',
smooth: true,
barWidth: 20,
areaStyle: {
opacity: 0.3
},
yAxisIndex: 1,
xAxisIndex: 1
}
return {
grid: [
{
bottom: '55%'
},
{
top: '58%'
}
],
xAxis: [
{
type: 'category',
data: chartData.map((item) => item.name),
gridIndex: 0
},
{
type: 'category',
data: chartData[selectedIndex]['electric'].map((item) => item.name),
gridIndex: 1
}
],
yAxis: [
{
type: 'value',
gridIndex: 0,
name: '单元:kWh'
},
{
type: 'value',
gridIndex: 1,
name: '单位:%'
}
],
series: [
{name: '上网电量', ...barOption, data: chartData.map(item => item.onlineValue)},
{name: '发电电量', ...barOption, data: chartData.map(item => item.electricValue)},
{
name: '上网电量使用率',
...lineOption,
data: chartData[selectedIndex]['online'].map((item) => item.value)
},
{
name: '发电率',
...lineOption,
data: chartData[selectedIndex]['electric'].map((item) => item.value)
}
]
}
}
此时页面效果如下图:
3.3 样式调整
如上图,图表看上去似乎不太美观,对分割线进行细调整即可。代码如下:
export const chartOptions = (chartData, selectedIndex) => {
// 略...
return {
// 略...
yAxis: [
{
type: 'value',
gridIndex: 0,
name: '单元:kWh',
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#063f6b'
}
}
},
{
type: 'value',
gridIndex: 1,
name: '单位:%',
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#063f6b'
}
}
}
],
// 略...
}
}
将分割线的颜色和线样式调整后,如下图:
3.4 图例组件
给电量图和线性图,添加图例组件legend。如果直接在配置项中添加legend属性,则主副表的图例数据全部显示在一起。配置代码如下:
export const chartOptions = (chartData, selectedIndex) => {
// 略...
return {
// 添加图例组件
legend: {},
// 略...
series: [
{name: '上网电量', ...barOption, data: chartData.map(item => item.onlineValue)},
{name: '发电电量', ...barOption, data: chartData.map(item => item.electricValue)},
{
name: '上网电量使用率',
...lineOption,
data: chartData[selectedIndex]['online'].map((item) => item.value)
},
{
name: '发电率',
...lineOption,
data: chartData[selectedIndex]['electric'].map((item) => item.value)
}
]
}
}
页面效果如下图:
此时,我们要的效果是,“上网电量”和“发电电量”图例显示在主图表上方,“上网电量使用率”和“发电率”图例显示在副图表上方。方法还是和xAxis和yAxis一样,将它们对象模式,改为数组模式即可,并且显示图例需要手动指定。配置代码如下:
export const chartOptions = (chartData, selectedIndex) => {
// 略...
return {
legend: [
{
data: ['上网电量', '发电电量'],
top: 10,
textStyle: {
color: '#FFF'
}
},
{
data: ['上网电量使用率', '发电率'],
top: '51%',
textStyle: {
color: '#FFF'
}
}
],
// 略...
series: [
{name: '上网电量', ...barOption, data: chartData.map(item => item.onlineValue)},
{name: '发电电量', ...barOption, data: chartData.map(item => item.electricValue)},
{
name: '上网电量使用率',
...lineOption,
data: chartData[selectedIndex]['online'].map((item) => item.value)
},
{
name: '发电率',
...lineOption,
data: chartData[selectedIndex]['electric'].map((item) => item.value)
}
]
}
}
页面效果如下图:
3.5 添加区域选中高亮效果
在主表中,添加选中区域高亮效果,通过splitArea修改区域背景色。配置项代码如下:
export const chartOptions = (chartData, selectedIndex) => {
// 略...
return {
// 略...
xAxis: [
{
type: 'category',
data: chartData.map((item) => item.name),
gridIndex: 0,
splitArea: {
show: true,
areaStyle: {
// 在官方文档中可见,此处Color为数组,分别对应X轴每个地区
// 所以须循环对每个区域进行背景设置,并通过selectedIndex修改选中区域样式
color: chartData.map(
(_, index) => selectedIndex === index ?
'rgba(29, 43, 104, .3)' : 'rgba(0, 0, 0, 0)'
)
}
}
},
{
type: 'category',
data: chartData[selectedIndex]['electric'].map((item) => item.name),
gridIndex: 1
}
],
// 略...
}
}
在xAxis横坐标系上,给选中区域添加背景色。效果如下图:
3.6 点击切换事件
当高亮效果添加好后,则要增加主图表的点击功能,通过点不同地区,切换数据,实现联动功能。
另外,对于一个坐标系区域点击触发事件,在之前一篇中已讲解,这里则直接使用,如不清楚的朋友,可以前去翻看一下。地址:ECharts的柱状图表中当数据量较少时不易触发点击事件使用getZr()方法来替换触发事件-CSDN博客
在页面初始化图表位置,增加点击事件。代码如下:
initialChart () {
// 初始化画板
this.chartRef = this.$echart.init(this.$refs['chart'])
// 点击事件
this.chartRef.getZr().on('click', (e) => {
// 定义当前坐标数组
const pointPixel = [e.offsetX, e.offsetY]
// 判断一个点是否在直角坐标系风格内,这里'grid'表示整个直角坐标系网格区域
if (this.chartRef.containPixel('grid', pointPixel)) {
const convertParam = this.chartRef.convertFromPixel({ seriesIndex: 0 }, pointPixel)
// 如果返回为空,则不执行后续操作
if (!convertParam) return
// 定义横向坐标索引
this.selectedIndex = parseInt(convertParam[0])
// 重新渲染图表
this.renderChart()
}
})
this.renderChart()
}
此时,点击各个地区,可以修改选中区域的高亮效果,并且使用率线性图表数据也能实时更新了。如下图:
此篇就先讲到这了,希望对大家会有所帮助~