本文已参与「新人创作礼」活动,一起开启掘金创作之路。
echart的双y轴且可选图例的图表组件
一、效果图
二、构建组件
示例用的是vue和element ui演示的,对多选做了限制,只能同时选择2个
代码如下(示例):
<template>
<div style="background:#ffffff">
<div id="income" style="height:80vh;width:100%"></div>
<div style="height: 70px; margin-left: 18%">
<!-- 选择图例 -->
<el-checkbox-group
v-model="lengendList"
@change="lengendChange"
size="mini"
:min="0"
:max="2"
>
<el-checkbox
v-for="city in lengendData"
border
:label="city"
:key="city"
>{{ city }}</el-checkbox
>
</el-checkbox-group>
</div>
</div>
</template>
<script>
//引入所需的echarts组件
import * as echarts from "echarts/core";
import { LineChart, BarChart } from "echarts/charts";
import { CanvasRenderer } from "echarts/renderers";
import {
GridComponent,
TooltipComponent,
TitleComponent,
LegendComponent,
ToolboxComponent,
} from "echarts/components";
echarts.use([
CanvasRenderer,
LineChart,
BarChart,
TooltipComponent,
GridComponent,
TitleComponent,
LegendComponent,
ToolboxComponent,
]);
export default {
name: 'myEchart',
props: ['listData','title'],//父组件传入的数据和表名
data() {
return {
// 图表的数据
incomeChartData: {
xAxis: [],
reqSmt: [],
resSmt:[],
uniShowSmt:[],
uniClkSmt:[],
auctionPrice:[],
winPrice:[],
profit:[],
},
//图例的选项
lengendData: [
"请求数",
"填充数",
"展示数",
"点击数",
"支出",
"收入",
"利润",
],
//默认选择的图例
lengendList: ["展示数"],
//图例的显示与否
lengendList2: {
请求数: false,
填充数: false,
展示数: true,
点击数: false,
支出: false,
收入: false,
利润: false,
},
timer: undefined,
};
},
//监视listData数据,数据改变就重新初始化图表
watch: {
listData () {
this.initIncomeChar();
}
},
mounted() {
//图表的大小随浏览器的大小变化而变化
window.onresize = () => {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.incomeChart.resize();
}, 100);
};
},
methods: {
//得到dom元素,初始化图表
initIncomeChar() {
var chartDom = document.getElementById("income");
this.incomeChart = echarts.init(chartDom);
this.getIncomeData(this.listData);//对数据进行处理
},
//图表配置文件
incomeSetOption() {
const option = {
title: {
text: this.title,
left: "center",
textStyle: {
color: "#333",
lineHeight: 50,
},
},
tooltip: {
trigger: "axis",
},
legend: {
data: this.lengendList,
selected: this.lengendList2,
top: "50",
textStyle: {
fontSize: 16,
},
itemHeight: 15,
bottom: "20",
height: "30",
},
grid: {
top: "100",
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
toolbox: {
itemSize: 20,
right: "3%",
top: "2%",
feature: {
//设置多个图表的功能组件
dataZoom:[{
type:"inside"
}],
magicType: {
type: ['line', 'bar']
},
//对数据视图进行表格化,更好的观看性
dataView:{
readOnly:true,
optionToContent: function(opt) {
var axisData = opt.xAxis[0].data;
var series = opt.series;
var table = '<table style="width:100%;text-align:center"><tbody><tr>'
+ '<td>时间</td>'
+ '<td>' + series[0].name + '</td>'
+ '<td>' + series[1].name + '</td>'
+ '<td>' + series[2].name + '</td>'
+ '<td>' + series[3].name + '</td>'
+ '<td>' + series[4].name + '</td>'
+ '<td>' + series[5].name + '</td>'
+ '<td>' + series[6].name + '</td>'
+ '</tr>';
for (var i = 0, l = axisData.length; i < l; i++) {
table += '<tr>'
+ '<td>' + axisData[i] + '</td>'
+ '<td>' + series[0].data[i] + '</td>'
+ '<td>' + series[1].data[i] + '</td>'
+ '<td>' + series[2].data[i] + '</td>'
+ '<td>' + series[3].data[i] + '</td>'
+ '<td>' + series[4].data[i] + '</td>'
+ '<td>' + series[5].data[i] + '</td>'
+ '<td>' + series[6].data[i] + '</td>'
+ '</tr>';
}
table += '</tbody></table>';
return table;
}
},
saveAsImage: {}
},
},
xAxis: {
type: "category",
boundaryGap: true,
data: this.incomeChartData.xAxis,
},
//y轴设置两个,在下面的yAxisIndex配置项中,0和1分别代表设置的这两个y轴
yAxis: [
{
type: "value",
axisLine: {
show: true,
},
},
{
type: "value",
axisLine: {
show: true,
},
},
],
series: [
{
name: "请求数",
type: "line",
//通过查找选中的图例有没有自己来决定是显示在第几个y轴上
//这样最后选择的两个图例中,肯定一个为0,一个为1 , 这样保证了两个不同的图例显示在不同的y轴
yAxisIndex:
this.lengendList.indexOf("请求数") == -1
? 0
: this.lengendList.indexOf("请求数"),
data: this.incomeChartData.reqSmt,
},
{
name: "填充数",
type: "line",
yAxisIndex:
this.lengendList.indexOf("填充数") == -1
? 0
: this.lengendList.indexOf("填充数"),
data: this.incomeChartData.resSmt,
},
{
name: "展示数",
type: "line",
yAxisIndex:
this.lengendList.indexOf("展示数") == -1
? 0
: this.lengendList.indexOf("展示数"),
data: this.incomeChartData.uniShowSmt,
},
{
name: "点击数",
type: "line",
yAxisIndex: 1,
yAxisIndex:
this.lengendList.indexOf("点击数") == -1
? 0
: this.lengendList.indexOf("点击数"),
data: this.incomeChartData.uniClkSmt,
},
{
name: "支出",
type: "line",
yAxisIndex: 1,
yAxisIndex:
this.lengendList.indexOf("支出") == -1
? 0
: this.lengendList.indexOf("支出"),
data: this.incomeChartData.auctionPrice,
},
{
name: "收入",
type: "line",
yAxisIndex:
this.lengendList.indexOf("收入") == -1
? 0
: this.lengendList.indexOf("收入"),
data: this.incomeChartData.winPrice,
},
{
name: "利润",
type: "line",
yAxisIndex:
this.lengendList.indexOf("利润") == -1
? 0
: this.lengendList.indexOf("利润"),
data: this.incomeChartData.profit,
},
],
};
option && this.incomeChart.setOption(option);
},
//得到图表中的数据
getIncomeData(data) {
this.incomeChartData = {
xAxis: [],
reqSmt: [],
resSmt: [],
uniShowSmt: [],
uniClkSmt: [],
auctionPrice: [],
winPrice: [],
profit: [],
};
//一般父组件给的数据是按时间从大到小排,所以我们需要反转数据,这样在图表中才能从小到大排,这样在图表中才更加直观
//反转数据后获取自己想要的数据
data.reverse().forEach((item) => {
this.incomeChartData.xAxis.push(item.reportTime);
this.incomeChartData.reqSmt.push(item.reqSmt);
this.incomeChartData.resSmt.push(item.resSmt);
this.incomeChartData.uniShowSmt.push(item.uniShowSmt);
this.incomeChartData.uniClkSmt.push(item.uniClkSmt);
this.incomeChartData.auctionPrice.push(item.auctionPrice);
this.incomeChartData.winPrice.push(item.winPrice);
this.incomeChartData.profit.push(item.profit);
});
data.reverse();//反转数据后应该反转回来,不然会影响原数据
this.incomeSetOption();//获取到数据后渲染图表
},
lengendChange() {
// 将图例的显示先全部设为false,再将选中的图例设为true
for (let i = 0; i < this.lengendData.length; i++) {
this.lengendList2[this.lengendData[i]] = false;
}
for (let i = 0; i < 2; i++) {
this.lengendList2[this.lengendList[i]] = true;
}
//选择图例后重新渲染图表
this.incomeSetOption();
},
},
};
</script>