一、柱状图
1. 数据相差过大时,过小数据不显示
解决方法:设置barMinheight属性。
2. 由于设置barMinheight属性后,导致为0的数据也会显示高度
解决方法:将series中的data进行过滤,为 0 的数据转化为 - 。
series: _.map(chartData.seriesData, (row, i) => {
return {
name: row.name,
type: 'bar',
stack: '举报单',
barMinHeight: 3,
data: this.filterZero(row.data),
itemStyle: {
normal: {
color: this.chartColorList[i]
}
}
}
})
})
},
filterZero(data) {
return _.map(data, (row) => {
if (row === 0) {
return '-';
}
return row
})
}
3. 设置柱状图粗细大小
- barWidth:设置每列宽度;
- barMinWidth:设置每列最小宽度;
- barMaxWidth:设置每列最大宽度;
series: _.map(chartData.seriesData, (row, i) => {
return {
name: row.name,
type: 'bar',
barMaxWidth: 40,
data: row.data || [],
}
})
4. tooltip根据值的大小进行排序
方法:修改tooltip 的 formatter,按照升序排列。
tooltip: {
trigger: 'axis',
formatter: function (params) {
let tooltipString = [];
let newParams = [...params];
newParams.sort((a, b) => {
return a.value - b.value
});
newParams.forEach((p) => {
const cont = p.marker + ' ' + p.seriesName + ': ' + p.value + '<br/>';
tooltipString.push(cont);
});
return tooltipString.join('');
}
}
5. legend添加全选/全不选功能
原理: 在 option 的 legend 里面有一个 selected 属性,它对应的是一个对象,结构如下:{0:true,1:true,3:true,9:true…},当我们把里面的type都设置成true,就是正常情况下全部显示legend的样子;当全部为false,则没有legend显示即为空图表。我们可以通过设置selected属性从而对图表进行全选和全不选的渲染。
代码如下:
- 在legend 和 series 下面添加一个全选:
legendData.unshift('全选')
seriesData.unshift({name: '全选', data: []})
- 在option中的egend添加全选的select属性,作为设置全选/全不选的flag:
legend: {
type: 'scroll',
icon: 'circle',
itemWidth: 15,
bottom: 0,
data: data,
selected: {
'全选': true
}
}
- 添加 legendselectchanged 事件:
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.barchart);
this.setOptions(this.chartData);
// 核心代码
this.listenLegendSelectChanged()
},
listenLegendSelectChanged() {
let _this = this;
let option = this.chart.getOption();
let data = option.legend[0].data;
this.chart.on('legendselectchanged', function (params) {
let selected = params.selected;
let name = params.name;
if (name == '全选') {
let selectedData = {};
if(option.legend[0].selected['全选'] === true){
for (let key in data) {
selectedData[data[key]] = false;
}
}else{
for (let key in data) {
selectedData[data[key]] = true;
}
}
option.legend[0].selected = selectedData;
_this.chart.setOption(option);
}
});
}
}
效果:
6. 修改legend形状
legend: {
type: 'scroll',
icon: 'circle',
bottom: 0,
data: [
{
name: '全选',
icon: 'rect',
color: '#333'
},
...
]
}
二、柱状图,折线图
1. 图例数据太多导致与图表重合
解决方法一:添加 scroll 属性,对图例设置滚动效果。
legend: {
// 设置滚动效果
type: 'scroll',
// 设置每个图例的宽度
itemWidth: 15,
data: chartData.legendData,
bottom: 0
}
解决方法二:若要图例保持多行展示,便不能对图例设置滚动效果,需要设置 grid 属性调整图表位置,避免重合。
grid: {
bottom: '20%'
},
legend: {
itemWidth: 15,
data: chartData.legendData || [],
bottom: 0
}
注意:多数情况下,grid的值需要 动态设置 ,根据 legend 数量多少,来决定 grid 设置多少。
如果设置一个固定的值,可能legend展示两行时刚好,但是展示5行时,又会与图表重合;
若设置的过大,虽然legend展示5行时,不会有问题,但是展示两行时,就会看起来空隙较大,不美观。
grid: {
bottom: chartData.legendData.length > 20 ? this.getGridBottomValue(chartData.legendData.length) : '20%'
}
grid bottom的计算公式:
getGridBottomValue(legendLength) {
return `${Math.floor(legendLength / 10) * 10}%`
}
2. 在title和图表之间添加多选下拉框
我们知道 title 和 图表 都是由echarts生成的一个 canvas 标签,如果想在上面添加一些元素,可以通过 绝对定位 设置上去。
首先,我们需要通过 grid 的 top 属性调整 title 和 图表 之间的距离,使之足够放下一个下拉框:
grid: {
top: '15%'
}
然后,在echarts的父元素下面,放入我们的下拉框(即select为echarts的兄弟元素):
<div class="chart-wrapper">
<el-select size="mini" v-model="reportType" placeholder="请选择举报类型" @change="reportTypeChange">
<el-option label="全选类型" value="0" key="0"></el-option>
<el-option v-for="(value,key,i) in reportTypeData" :key="key" :label="value" :value="key"></el-option>
</el-select>
<div style="width: 100%;height:400px;" class="bar-chart" ref="barchart"></div>
</div>
最后,我们需要对 echarts的父元素 和 select 进行定位,并调整距离:
.chart-wrapper {
display: inline-block;
width: 48%;
height: 450px;
.el-select {
display:block;
width:20%;
position: absolute;
top: 40px;
left: 40px;
z-index: 1;
}
}
注意:一定要设置select的 z-index ,并且使它的值大于图表以及图表父元素,否则你的下拉框有可能就无法触发了!
3. y轴根据不同的数据大小设置不同的单位
y轴不使用统一单位,当最小刻度大于 1000 时单位使用 k ,当最小刻度大于 1000000 时使用 M 。
yAxis: {
axisLabel: {
// 对y轴上面的值value进行单位转换
formatter(value) {
if (value < 1000) {
return value;
} else if (value < 1000000) {
return `${Math.floor(value / 1000)}K`;
} else {
return `${Math.floor(value / 1000000)}M`;
}
}
}
}
注意:关于x轴或y轴添加单位的方法可参考:echarts柱状图y轴数据添加单位的三种方式(vue项目)
4. 调整title的位置和样式
title: {
text: chartData.text,
// title的位置
x: '40px',
y: '0px',
textAlign: 'left',
// title的字体大小和样式
textStyle: {
fontSize: 16,
fontWeight: '500',
}
}
5. 坐标轴刻度线的设置
将y轴刻度线设置为虚线:
yAxis: {
splitLine: {
show: true,
lineStyle: {
type: 'dashed'
}
}
}
6. 获取和设置y轴最大刻度
通过yAxis.max和yAxis.min函数。
yAxis: {
min(value) {
// value.min 为当前图表y轴最小刻度值
return value.min - 20;
},
// value.max 为当前图表y轴最大刻度值
max(value) {
return value.max + 20;
}
}
7. 指定legend图例滚动到哪一页
legend: {
type: 'scroll',
// 默认图例展示第一页
scrollDataIndex: 0,
icon: 'circle',
data: chartData.legendData || [],
selected: {
'全选': true
}
}
当触发图例翻页时,记录当前图例索引:
listenLegendScroll(){
let _this = this;
this.chart.on('legendScroll', params => {
_this.scrollDataIndex = params.scrollDataIndex;
})
},
当重新生成图表时,指定图例滚动到刚才记录的位置:
...
let option = this.chart.getOption();
option.legend[0].scrollDataIndex = _this.scrollDataIndex;
this.chart.setOption(option);
...
三、饼图
1. 设置空心饼图
通过 series 下的 radius 属性来进行设置。
let option = {
series: [{
type: 'pie',
// 第一个参数是控制里面小圈的大小,第二个参数是控制外面大圈的大小
// 同时当只有一个参数时,如 radius : '55%'
// 这个属性可以设置图的大小
radius: ['40%', '60%'],
data: data
}]
}
2. 设置饼图的中间文字
通过 title 属性来进行设置。
let option = {
title: {
text: chartData.total, // 主标题
// 主标题位置
x: 'center',
y: 'center',
textStyle: { // 主标题样式
fontSize: '24',
color: '#06A17E',
fontweight: 700
},
subtext: '游戏总量', // 副标题
subtextStyle: { // 副标题样式
color: 'red',
fontSize: 14,
fontWeight: 500
}
}
};
3. tooltip 显示数量和百分比
通过 tooltip 下的 formatter 属性来自定义设置。
let option = {
tooltip: {
show: true, // 是否显示提示:true/false,默认为true
trigger: "item", // 触发类型, item/axis/none
// tooltip提示格式,支持字符串模板和回调函数
// {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
formatter: "{a} <br/>{b}: {c} ({d}%)",
backgroundColor: 'rgba(0,0,0,.5)', // 提示框背景
borderWidth: 1, // 提示框边框大小
borderColor: '#ff0000', // 提示框边框颜色
}
};
官方链接: tooltip. formatter
四、所有图表类型
1. echarts 重新赋值时,tooltip不更新
当数据发生改变,对echarts 重新赋值时,发现图表显示会存在一部分原来的数据,导致tooltip不更新。
解决方法:在重新赋值前,先使用 clear() 清除掉之前的图表。
watch: {
chartData: {
deep: true,
handler(newData) {
this.chart.clear();
this.chart = echarts.init(this.$refs.barchart);
this.setOptions(this.chartData)
// 之前的方法
// this.setOptions(newData)
}
}
}
2. 优化toolbox中数据视图dataview的样式
echarts中提供了dataView视图模式,但是里面的数据没有对整,整体看起来很乱,展示效果很差,我们可以在 optionTocontent 的回调函数中处理,调整为表格展示。
toolbox:{
show: true,
feature: {
dataView: {
show: true,
title: '数据视图',
//处理为表格展示
optionToContent: function (opt) {
let axisData = opt.xAxis[0].data;
let series = opt.series;
let tdHeads = '<td style="padding:0 10px">名称</td>';
series.forEach(function (item) {
tdHeads += '<td style="padding: 0 10px">'+item.name+'</td>';
});
let table = '<table border="1" style="margin-left:20px;border-collapse:collapse;font-size:14px;text-align:center;user-select:text;"><tbody><tr>'+tdHeads+'</tr>';
let tdBodys = '';
for (let i = 0, l = axisData.length; i < l; i++) {
for (let j = 0; j < series.length; j++) {
if(typeof(series[j].data[i]) == 'object'){
tdBodys += '<td>'+series[j].data[i].value+'</td>';
}else{
tdBodys += '<td>'+ series[j].data[i]+'</td>';
}
}
table += '<tr><td style="padding: 0 10px">'+axisData[i]+'</td>'+ tdBodys +'</tr>';
tdBodys = '';
}
table += '</tbody></table>';
return table;
}
},
mark: {show:true},
restore:{show:true},
magicType: {type: ['line', 'bar','pie']},
saveAsImage:{show:true}
}
}
默认的dataview效果:
调整后的dataview效果:
注意:如果想要table是可复制文字的,需要在table标签上添加 user-select: text; 属性。
3. tooltip提示内容分列显示
对于tooltip内容太多,超出图表的显示区域,导致显示不全的问题,可以自定义tooltip分成若干列显示。
tooltip: {
trigger: 'axis',
formatter: function (params) {
// tooltip分列显示:条数超过18项则分两列,超过40项分三列
let colWidth;
let width = 500;
if (params.length > 40) {
colWidth = '33.3%';
} else if (params.length > 18) {
colWidth = '50%';
} else {
width = 150;
colWidth = '100%';
}
let domString = '';
params.forEach((ele, index) => {
// 添加日期
if (ele && index === 0) {
domString += `<div>${ele.axisValue}</div>`;
}
domString += `<div style="float:left;width:${colWidth}">
<i style="width: 10px;height: 10px;display: inline-block;background: ${ele.color};border-radius: 10px;"></i>
<span>${ele.seriesName}: ${ele.data}</span>
</div>`
})
return `<div style="width: ${width}px;">${domString}<div>`;
},
position: function (point, params, dom, rect, size) {
return [point[1], 0]
}
},
效果:
显示3列时:
显示2列时:
正常显示1列时:
4. 让图表占满整个div容器
当我们对echarts图表设置宽高后可以发现,它并没有占满整个div容器,而是被压缩了。
<div style="width: 100%;height: 100%;" class="pie-chart" ref="piechart"></div>
解决方法:设置 grid 属性。
// 让图表占满容器
grid:{
top:"0px",
left:"0px",
right:"0px",
bottom:"0px"
}
5. y坐标轴标题文字居左显示
y轴 yAxis 中 name 属性只有垂直位置 nameLocation 属性,没有水平位置的设置,但是产品希望文字能够相对于y轴居左显示。
解决方法:通过官方文档发现 axisName 的 nameRotate 属性是根据 axisName 的中心做的旋转,所以使用 nameRotate:0.1 来做一下旋转就可以使 axisName 居左显示。
yAxis: {
name: '数量',
type: 'value',
// 旋转0.1,达到居左显示的效果
nameRotate: -0.1,
}
6. x轴y轴、刻度线等样式相关问题
(1)不显示坐标轴刻度线
通过设置 axisTick 属性,以 y轴 为例:
yAxis: {
axisTick:{
show:false
}
(2)不显示网格线
通过设置 splitLine 属性,以 x轴 为例:
xAxis:{
splitLine:{
show:false
}
}
(3)设置坐标轴颜色
通过设置 axisLine 属性,以 x轴 为例:
xAxis:{
axisLine: {
lineStyle: {
color: '#ccc',
width: 1
}
}
}
(4)设置X轴刻度间隔显示
通过设置 axisLabel 属性,以 x轴 为例:
xAxis: {
axisLabel:{
// 0:表示全部显示不间隔;auto:表示自动根据刻度个数和宽度设置间隔
interVal:9
}
}
(5)x轴的刻度和文字对齐
通过设置 xAixs.axisTick.alignWithLabel :
xAxis: {
axisTick: {
//x轴刻度相关设置:是刻度在文字的中间位置
alignWithLabel: true,
},
}
7. legend 图标大小,间距,位置以及与文字对齐
legend: {
data: ['处罚', '解处罚'],
// 设置图标形状
icon: 'rect',
// 设置图标大小
itemWidth: 15,
itemHeight: 15,
// 设置图标间距
itemGap: 30,
// 设置图标位置
bottom: -3,
// 设置图标文字样式
textStyle: {
color: '#464A52',
padding: [1, 1],
// 设置文字行高与图标高度一致
// 以此来达到文字与图标对齐的效果
lineHeight: 15
}
}
8. 自定义tooltip的icon和结构
formatter: function (val) {
let txt = val[0].name
return (val[0].name + '<br />' + val[0].marker + val[0].seriesName +':' +val[0].value +'亿元' + '<i class="el-icon-star-on"><i />')
}
总结
在使用echarts图表时,遇到了一些问题,在此做出总结。希望日后遇到相同的问题可以到在这里查找解决方法,快速解决。