ECharts常用配置项

前言

ECharts是我们常用的图表控件,功能特别强大,每次使用都要查API比较繁琐,这里就记录开发中常用的配置。

官网:https://echarts.apache.org/handbook/zh/get-started

配置项:https://echarts.apache.org/zh/option.html#title

第三方示例平台:https://www.makeapie.cn/echarts

主题:https://echarts.apache.org/zh/theme-builder.html

引用

安装

1
npm install echarts --save

依赖如下

1
2
3
4
"dependencies": {
"echarts": "^5.3.3",
"moment": "^2.29.4",
},

引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import * as echarts from 'echarts';

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 绘制图表
myChart.setOption({
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
});

设置渲染方式

方式选择

在软硬件环境较好,数据量不大的场景下,两种渲染器都可以适用,并不需要太多纠结。

在环境较差,出现性能问题需要优化的场景下,可以通过试验来确定使用哪种渲染器。

比如有这些经验:

  • 在须要创建很多 ECharts 实例且浏览器易崩溃的情况下(可能是因为 Canvas 数量多导致内存占用超出手机承受能力),可以使用 SVG 渲染器来进行改善。

    大略得说,如果图表运行在低端安卓机,或者我们在使用一些特定图表如 水球图 等,SVG 渲染器可能效果更好。

  • 数据量较大(经验判断 > 1k)、较多交互时,建议选择 Canvas 渲染器。

设置代码

1
2
3
4
5
6
7
// 使用 Canvas 渲染器(默认)
var chart = echarts.init(containerDom, null, { renderer: 'canvas' });
// 等价于:
var chart = echarts.init(containerDom);

// 使用 SVG 渲染器
var chart = echarts.init(containerDom, null, { renderer: 'svg' });

数据变化重新渲染

1
chart.setOption(option, notMerge, lazyUpdate);

或者:

1
2
3
4
5
chart.setOption(option, {
notMerge: false,
lazyUpdate: false,
silent: false
});

参数解释:

  • option
    图表的配置项和数据,具体见配置项手册。

  • notMerge

    可选,是否不跟之前设置的 option 进行合并,默认为 false,即合并。

  • lazyUpdate

    可选,在设置完 option 后是否不立即更新图表,默认为 false,即立即更新。

  • silent

    可选,阻止调用 setOption 时抛出事件,默认为 false,即抛出事件。

第二个参数notMerge,将它设置为true即不合并之前的options,使用新的options。

响应容器的大小

1
2
3
4
var myChart = echarts.init(document.getElementById('main'));
window.onresize = function() {
myChart.resize();
};

注意和VUE结合使用时,一定要等待DOM渲染完毕再调用,否则不生效。

1
2
3
4
5
async leftbar_click() {
this.show_left = !this.show_left;
await this.$nextTick();
this.echart && this.echart.resize()
}

除了直接调用 resize() 不含参数的形式之外,还可以指定宽度和高度,实现图表大小不等于容器大小的效果。

1
2
3
4
myChart.resize({
width: 800,
height: 400
});

VUE封装图表自动缩放

VUE封装组件,让图表随页面变化自动缩放。

@/assets/utils/debounce.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result

const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp

// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}

return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}

return result
}
}

@/assets/utils/chat_resize.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { debounce } from '@/assets/utils/debounce.js'

export default {
data() {
return {
$_mDom: null,
$_resizeHandler: null
}
},
mounted() {
this.initListener()
},
activated() {
if (!this.$_resizeHandler) {
this.initListener()
}
this.resize()
},
beforeDestroy() {
this.destroyListener()
},
deactivated() {
this.destroyListener()
},
methods: {
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.$_resizeHandler()
}
},
initListener() {
this.$_resizeHandler = debounce(() => {
this.resize()
}, 100)
//窗口缩放时触发
window.addEventListener('resize', this.$_resizeHandler)
this.$_mDom = document.getElementById('app')
this.$_mDom && this.$_mDom.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
destroyListener() {
window.removeEventListener('resize', this.$_resizeHandler)
this.$_resizeHandler = null
this.$_mDom && this.$_mDom.removeEventListener('transitionend', this.$_sidebarResizeHandler)
},
resize() {
const { chart } = this
chart && chart.resize()
}
}
}

自定义图表组件中调用

1
2
3
4
5
6
7
8
9
10
11
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js"

export default {
mixins: [resize],
data() {
return {
chart: null,
};
},
}

完整示例

ZChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from "echarts";
import resize from "@/assets/utils/chat_resize.js";

export default {
name: "ZBarChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "600px",
},
height: {
type: String,
default: "400px",
},
title: {
type: String,
default: "",
},
groupField: {
type: String,
default() {
return "subject";
},
},
keyFields: {
type: Array,
default() {
return ["name"];
},
},
valueFieldNames: {
type: Array,
default() {
return ["得分", "历史得分"];
},
},
valueFields: {
type: Array,
default() {
return ["score", "socreHistory"];
},
},
dataList: {
type: Array,
default() {
return require("@/assets/json/user_score_list.json");
},
},
},
data() {
return {
chart: null,
};
},
watch: {
dataList: function () {
this.initChart();
},
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}

let groupField = this.groupField;
let keyFields = this.keyFields;
let valueFieldNames = this.valueFieldNames;
let valueFields = this.valueFields;
let dataList = this.dataList;

if (groupField) {
if (keyFields.indexOf(groupField) !== -1) {
keyFields.splice(keyFields.indexOf(groupField), 1);
}
}
let groupNameArr = [];
let nameArr = [];
for (let i = 0; i < dataList.length; i++) {
let item = dataList[i];
if (groupField) {
if (groupNameArr.indexOf(item[groupField]) === -1) {
groupNameArr.push(item[groupField]);
}
}
let keyValue = "";
for (let j = 0; j < keyFields.length; j++) {
if (keyValue) {
keyValue += "_" + item[keyFields[j]];
} else {
keyValue += item[keyFields[j]];
}
}
if (nameArr.indexOf(keyValue) === -1) {
nameArr.push(keyValue);
}
}

let seriesArr = [];

if (this.groupField) {
//设置分组字段
for (let i = 0; i < valueFields.length; i++) {
let valueArr = new Array(groupNameArr.length).fill(
new Array(nameArr.length).fill(0)
);
valueArr = JSON.parse(JSON.stringify(valueArr));
for (let j = 0; j < dataList.length; j++) {
let item = dataList[j];
let groupValue = item[groupField];
let groupIndex = groupNameArr.indexOf(groupValue);
let nameItem = "";
for (let k = 0; k < keyFields.length; k++) {
if (nameItem) {
nameItem += "_" + item[keyFields[k]];
} else {
nameItem += item[keyFields[k]];
}
}

let valueIndex = nameArr.indexOf(nameItem);
if (groupIndex !== -1 && valueIndex !== -1) {
valueArr[groupIndex][valueIndex] += item[valueFields[i]];
}
}

for (let j = 0; j < groupNameArr.length; j++) {
seriesArr.push({
name: groupNameArr[j] + "-" + valueFieldNames[i],
type: "bar",
data: valueArr[j],
stack: i + "-" + j,
});
}
}
} else {
//未设置分组字段
for (let i = 0; i < valueFields.length; i++) {
let valueArr = new Array(nameArr.length).fill(0);
valueArr = JSON.parse(JSON.stringify(valueArr));
for (let j = 0; j < dataList.length; j++) {
let item = dataList[j];
let nameItem = "";
for (let k = 0; k < keyFields.length; k++) {
if (nameItem) {
nameItem += "_" + item[keyFields[k]];
} else {
nameItem += item[keyFields[k]];
}
}

let valueIndex = nameArr.indexOf(nameItem);
if (valueIndex !== -1) {
valueArr[valueIndex] += item[valueFields[i]];
}
}
seriesArr.push({
name: valueFieldNames[i],
type: "bar",
data: valueArr,
tooltip: {
formatter: function (params) {
return (
params.seriesName +
"-" +
valueFieldNames[i] +
"<br>" +
params.name +
":" +
params.value[params.dimensionNames[params.encode.y[0]]]
);
},
},
});
}
}

let opts = {
title: {
text: this.title,
top: 0,
textStyle: {
fontWeight: "bold",
fontSize: 14,
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
legend: {
show: true,
top: 2,
right: 2,
},
color: [
"#20afff",
"#2cd9ff",
"#9dfff0",
"#77fef6",
"#fffc91",
"#fdc67f",
"#f2528b",
],
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true,
},
xAxis: [
{
type: "category",
data: nameArr,
axisTick: {
alignWithLabel: true,
},
axisLabel: {
rotate: 0,
},
},
],
yAxis: [
{
type: "value",
},
],
series: seriesArr,
};
this.chart.setOption(opts);
},
},
};
</script>

具体的数据

user_score_list.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
[
{
"id": 1001,
"name": "王宁",
"subject": "语文",
"score": 80,
"sex": "女",
"socreHistory": 100
},
{
"id": 1002,
"name": "王宁",
"subject": "数学",
"score": 60,
"sex": "女",
"socreHistory": 80
},
{
"id": 1003,
"name": "王宁",
"subject": "英语",
"score": 93,
"sex": "女",
"socreHistory": 60
},
{
"id": 1004,
"name": "张瑞红",
"subject": "语文",
"score": 99,
"sex": "女",
"socreHistory": 30
},
{
"id": 1005,
"name": "张瑞红",
"subject": "数学",
"score": 70,
"sex": "女",
"socreHistory": 80
},
{
"id": 1006,
"name": "张瑞红",
"subject": "英语",
"score": 80.5,
"sex": "女",
"socreHistory": 60
},
{
"id": 1007,
"name": "王中露",
"subject": "语文",
"score": 60,
"sex": "男",
"socreHistory": 70
},
{
"id": 1008,
"name": "王中露",
"subject": "数学",
"score": 90,
"sex": "男",
"socreHistory": 100
},
{
"id": 1009,
"name": "王中露",
"subject": "英语",
"score": 70,
"sex": "男",
"socreHistory": 90
},
{
"id": 1010,
"name": "郭忠博",
"subject": "语文",
"score": 80,
"sex": "男",
"socreHistory": 60
},
{
"id": 1011,
"name": "郭忠博",
"subject": "数学",
"score": 70,
"sex": "男",
"socreHistory": 50
},
{
"id": 1012,
"name": "郭忠博",
"subject": "英语",
"score": 99,
"sex": "男",
"socreHistory": 70
},
{
"id": 1013,
"name": "雍文秀",
"subject": "语文",
"score": 30,
"sex": "女",
"socreHistory": 80
},
{
"id": 1014,
"name": "雍文秀",
"subject": "数学",
"score": 100,
"sex": "女",
"socreHistory": 98
},
{
"id": 1015,
"name": "雍文秀",
"subject": "英语",
"score": 98,
"sex": "女",
"socreHistory": 65
}
]

配置项

背景色

1
2
3
4
5
6
7
8
9
10
backgroundColor: new echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [
{
offset: 0,
color: "#431ab8",
},
{
offset: 1,
color: "#471bba",
},
]),

graphic 背景图

注意

这个会在图表的下层,不能实现覆盖在图标上的效果。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
graphic: [
{
type: 'group',
left: '1%',
width: 100,
height: 100,
top: 'middle', // 相对父元素居中
rotation: 0,
children: [
{
type: 'circle',
left: 'center', // 相对父元素居中
top: 'middle', // 相对父元素居中
shape: {
cx: 50,
cy: 50,
r:30
},
style: {
fill: '#ff0000',
stroke: '#ff0000',
lineWidth: 2,
shadowBlur: 8,
shadowOffsetX: 3,
shadowOffsetY: 3,
shadowColor: 'rgba(0,0,0,0.3)'
}
},
{
type: 'text',
left: 'center', // 相对父元素居中
top: 'middle', // 相对父元素居中
style: {
fill: '#ffffff',
text: "123",
font: '14px Microsoft YaHei'
}
}
]
}
],

恢复/保存

1
2
3
4
5
6
toolbox: {
feature: {
restore: {},
saveAsImage: {},
},
},

title 标题

标题组件,包含主标题和副标题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
title:{
show:true,
text : '',
textStyle:{
color: '#333' ,
fontStyle: 'normal' ,
fontWeight: 'bolder' ,
fontFamily: 'sans-serif' ,
fontSize: 18 ,
lineHeight ... ,
width ... ,
height ... ,
textBorderColor ... ,
textBorderWidth ... ,
textBorderType: 'solid' ,
textBorderDashOffset: 0 ,
textShadowColor: 'transparent' ,
textShadowBlur: 0 ,
textShadowOffsetX: 0 ,
textShadowOffsetY: 0 ,
overflow: 'none' ,
ellipsis: '...' ,
},
subtext: '(万元)' ,
subtextStyle:{},
zlevel: 0 ,
z: 2 ,
left: 'auto' ,
top: 'auto' ,
right: 'auto' ,
bottom: 'auto' ,
}

xAxis/yAxis(x轴/y轴)

直角坐标系 grid 中的 x/y 轴,一般情况下单个 grid 组件最多只能放上下两个 x/y 轴,多于两个 x/y 轴需要通过配置 offset 属性防止同个位置多个x/y 轴的重叠。

基本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xAxis:[
{
type: "category",
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
axisTick: {
alignWithLabel: true,
},
axisLabel: {
rotate: 20
},
nameLocation: "end",
name: "%"
},
]

axisTick:坐标轴刻度相关设置。

axisLabel:坐标轴刻度标签的相关设置。

name:相关的是轴线一侧的文字,如显示单位。

自定义标签内容

1
2
3
4
5
6
7
8
option = {
yAxis: {
axisLabel: {
formatter: '{value} 元',
align: 'center'
}
}
};

设置文字样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
xAxis: [
{
type: "category",
data: nameArr,
axisTick: {
alignWithLabel: true,
},
axisLabel: {
rotate: 30,
textStyle: {
color: "#A5ADD3", //坐标值得具体的颜色
fontSize: 10,
},
},
},
],

文字过长处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
xAxis: [
{
type: 'category',
data: nameArr,
axisTick: {
alignWithLabel: true
},
axisLabel: {
rotate: 60,
formatter (para) {
if (para.length > 6) {
para = para.substr(0, 6) + '...'
}
return para
}
}
}
],

不显示横线

1
2
3
4
yAxis: {
type: "value",
splitLine: false,
},

设置值区间

1
2
3
4
5
yAxis: {
type: "value",
min: 6.2,
max: 7.0,
},

设置单位

1
2
3
4
5
6
7
8
9
10
11
yAxis: [
{
type: "value",
splitLine: false,
name: "% ",
nameLocation: "end",
nameTextStyle: {
align: "right",
},
},
],

辅助线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
yAxis: [
{
type: "value",
max:5,
axisPointer: {
show: true,
value: 3.70,
type: "line",
lineStyle: {
color: "#ff0000"
},
label: {
show: true
}
}
},
],

不显示刻度

1
2
3
4
5
6
7
xAxis: {
type: 'category',
data: nameArr,
axisTick: {
show: false
}
},

grid

直角坐标系内绘图网格,单个 grid 内最多可以放置上下两个 X 轴,左右两个 Y 轴。可以在网格上绘制折线图柱状图散点图(气泡图)

1
2
3
4
5
6
7
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true
},

四个方向都可以用百分比和具体数值

containLabeltrue时,left right top bottom width height 决定的是包括了坐标轴标签在内的所有内容所形成的矩形的位置。

legend

图例组件。

图例组件展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
legend: {
type: 'plain',
orient: 'horizontal',
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
bottom: 20,
align: 'left',
textStyle: {
color: '#333',
},
itemGap: 10,
formatter: (name) => {
let item = null;
for (const _item of chartData) {
if (_item.chainName === name) {
item = _item;
break;
}
}
if (item) {
return name + ' ' + item.total + '次 ' + ((item.successCount * 100) / item.total).toFixed(1) + '%';
} else {
return name;
}

},
},

其中:

  • legend.type: plain/scroll
  • legend.orient: horizontal/vertical
  • legend.itemGap: 图例每项之间的间隔。横向布局时为水平间隔,纵向布局时为纵向间隔。
  • legend.icon: circle, rect, roundRect, triangle, diamond, pin, arrow, none

tooltip

悬浮框组件。

1
2
3
4
tooltip: {
show: true,
formatter: '{b0}成功率: {c0}%',
},

或者

1
2
3
4
5
6
tooltip: {
show: true,
formatter: (p) => {
return p.name + ":" + p.percent + "%"
},
},

或者

1
2
3
4
5
6
tooltip: {
show: true,
formatter (para) {
return para.name + '\n\n' + that.$qianFunc(para.data.value)
}
},

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
tooltip: {
show: true,
formatter: (p) => {
let i = p.dataIndex - 1;
let item = data4_chart5[i];
return [
p.marker + "[融资单位名称]",
"&nbsp;&nbsp;&nbsp;&nbsp;" +item.danwei,
p.marker + "[借款机构名称]",
"&nbsp;&nbsp;&nbsp;&nbsp;" + item.jigou,
p.marker + "[借款性质]",
"&nbsp;&nbsp;&nbsp;&nbsp;" + + item.type,
p.marker + "[金额(折算人民币)]",
"&nbsp;&nbsp;&nbsp;&nbsp;" + + item.money
].join("<br>")
},
},

其中

p.marker是小圆点

dataZoom

dataZoom 组件 用于区域缩放,从而能自由关注细节的数据信息,或者概览数据整体,或者去除离群点的影响。

1
2
3
4
5
6
7
8
9
10
11
dataZoom: {
right: '2%', //下滑块距离x轴底部的距离
top: '5%',
height: '90%', //下滑块手柄的高度调节
width: 20,
type: 'slider', //类型,滑动块插件
show: true, //是否显示下滑块
yAxisIndex: [0], //选择的y轴
start: 0, //初始数据显示多少
end: 100, //初始数据最多显示多少
},

series

折线图

1
2
3
4
5
6
7
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}
]

其中smooth: true是曲线。

不显示点

1
2
3
4
5
6
7
8
9
10
seriesArr.push(
{
data: value2Arr,
type: 'line',
smooth: true,
symbol: false,
symbolSize: 0,
animationDuration: 1600,
yAxisIndex: 1,
});

主要是symbolSize: 0,

柱状图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
series: [
{
type: 'bar',
showBackground: false,
data: valueData,
barWidth: 16,
itemStyle: {
normal: {
color: '#3c90f7',
barBorderRadius: [8, 8, 0, 0],
},
},
emphasis: {
itemStyle: {
color: specialColor,
},
},
},
],

其中:

  • emphasis:高亮的图形样式和标签样式。

横向柱状图

只需反转xAxis和yAxis即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 grid: {
top: 40,
left: "2%",
right: 60,
bottom: 30,
containLabel: true,
},
yAxis: [
{
type: "category",
data: nameArr,
axisTick: {
alignWithLabel: true,
},
axisLabel: {
rotate: 0
}
},
],
xAxis: [
{
type: "value",
name: "百万元 ",
nameLocation: "end",
nameTextStyle: {
align: "left",
},
},
],

上下叠加

1
2
3
4
5
6
7
8
9
10
11
let seriesArr = [];
for (let i = 0; i < groupNameArr.length; i++) {
let s = {
name: groupNameArr[i],
type: "bar",
data: valueArr[i],
barWidth: 30,
stack: "总量",
};
seriesArr.push(s);
}

添加"stack": "总量",即可

前后叠加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let seriesArr = [];
for (let i = 0; i < groupNameArr.length; i++) {
let s = {
name: groupNameArr[i],
type: "bar",
data: valueArr[i],
barWidth: 30,

};
if (i > 0) {
s.barGap = "-100%";
}
seriesArr.push(s);
}

每个bar单独颜色

1
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1, data: valueArr, colorBy: "data"},

饼图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
series: [
{
type: 'pie',
radius: ['30%', '45%'],
center: ['50%', '30%'],
hoverAnimation: true,
itemStyle: {
normal: {
borderWidth: 2,
borderColor: '#ffffff',
label: {
show: true,
position: 'outside',
color: '#ddd',
formatter: function (params) {
var percent = 0;
var total = 0;
for (var i = 0; i < mydata.length; i++) {
total += mydata[i].value;
}
percent = ((params.value / total) * 100).toFixed(0);
if (params.name !== '') {
return '名称:' + params.name + '\n' + '\n' + '比例:' + percent + '%';
} else {
return '';
}
},
},
labelLine: {
length: 30,
length2: 100,
show: true,
color: '#00ffff',
},
},
},
label: {
show: false,
},
data: mydata,
labelLine: {
show: true,
},
},
],

南丁格尔玫瑰图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
series: [
{
type: 'pie',
center: ['40%', '50%'],
radius: ['40%', '80%'],
hoverAnimation: true,
startAngle: 135,
z: 0,
roseType: 'radius',
itemStyle: {
borderRadius: 0,
},
label: {
show: false,
},
labelLine: {
show: false,
},
data: chartData,
}
]

series[i].label

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
type: 'pie',
center: ['40%', '50%'],
radius: ['40%', '80%'],
hoverAnimation: true,
z: 0,
roseType: 'radius',
itemStyle: {
borderRadius: 0,
},
label: {
show: false,
},
labelLine: {
show: false,
},
data: chartData,
}

显示在内部

1
2
3
4
5
6
7
8
9
10
label: {
show: true,
position: 'inner',
textStyle: {
color: '#fff',
fontWeight: 'bold',
fontSize: 12,
lineHeight: 20,
}
},

series[i].labelLine

1
2
3
4
5
labelLine: {
show: true,
length: 0,
length2: 4,
}

series[i].markLine 标识线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
markLine: {
data: [
{
name: "一年期LPR",
xAxis: 0,
yAxis: 3.7,
label: {
formatter: "一年期LPR",
fontSize: "10",
color: "#FA6400",
},
lineStyle: {
type: "dashed",
color: "#FA6400",
},
},
{
name: "五年期LPR",
xAxis: 0,
yAxis: 4.65,
label: {
formatter: "五年期LPR",
fontSize: "10",
color: "#B550CB",
},
lineStyle: {
type: "dashed",
color: "#B550CB",
},
},
],
}

series[i].itemStyle.color 设置图形颜色

1
2
3
4
5
6
7
itemStyle: {
borderWidth: 0,
borderColor: '#ffffff',
color: function (para) {
return para.data.color
}
}

多个图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
option = {
xAxis: [
{ type: 'category', gridIndex: 0, data: ['1月', '2月', '3月'] },
{ type: 'category', gridIndex: 1, data: ['4月', '5月', '6月'], position: 'top' },
],
yAxis: [
{ gridIndex: 0 },
{ gridIndex: 1, inverse: true }
],
grid: [
{ bottom: '55%' },
{ top: '55%' }
],
series: [
// 这几个系列会出现在第一个直角坐标系中
{ type: 'bar', data: [1, 5, 10] },
{ type: 'bar', data: [2, 4, 3] },
// 这几个系列会出现在第二个直角坐标系中,
{ type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [2, 5, 8] },
{ type: 'line', xAxisIndex: 1, yAxisIndex: 1, data: [8, 2, 6] },
],
};

关键的两个属性:

  • xAxis中的position: 'top'

  • yAxis中的inverse: true

效果如下:

image-20211230172045063

渐变色

线性渐变

1
2
3
4
5
6
7
8
9
const specialColor = {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{ offset: 0, color: '#46c6fe' }, { offset: 1, color: '#6fa0fa' }],
global: false // 缺省为 false
}

径向渐变,前三个参数分别是圆心 x, y 和半径,取值同线性渐变

1
2
3
4
5
6
7
8
9
10
11
12
var specialColor = {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.5,
colorStops: [{
offset: 0, color: 'red' // 0% 处的颜色
}, {
offset: 1, color: 'blue' // 100% 处的颜色
}],
global: false // 缺省为 false
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
option={
series: [
{
type: 'bar',
showBackground: false,
data: [1,3,5,2,4],
barWidth: 16,
itemStyle: {
color: '#3c90f7',
barBorderRadius: [8, 8, 0, 0],
},
emphasis: {
itemStyle: {
color: specialColor,
},
},
},
],
}

symbol

默认图形

ECharts 提供的标记类型包括

'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'

本地图片

1
2
3
4
let symbolImg = 'image://'+ require('@/assets/image/map-logo.png');
{
symbol:symbolImg
}

图片URL

可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI

URL 为图片链接例如:

1
'image://http://xxx.xxx.xxx/a/b.png'

图片DataURI

URL 为 dataURI 例如:

1
'image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'

矢量图Path

可以通过 'path://' 将图标设置为任意的矢量路径。这种方式相比于使用图片的方式,不用担心因为缩放而产生锯齿或模糊,而且可以设置为任意颜色。路径图形会自适应调整为合适的大小。路径的格式参见 SVG PathData。可以从 Adobe Illustrator 等工具编辑导出。

例如:

1
'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z'

示例

饼图

基本

image-20220509152035094

/components/ZPieChart01.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js";

export default {
name: "PieChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Array,
default: () => {
return [{
name: "春",
value: 400
}, {
name: "夏",
value: 100
}, {
name: "秋",
value: 200
}, {
name: "冬",
value: 500
}]
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let chartData = this.chartData || [];
let legend_data = [];
let total = 0;
for (const item of chartData) {
legend_data.push(item.name);
total += item.value;
}
let dian_arr = [];
for (let i = 0; i < 60; i++) {
dian_arr.push(1);
}

let opts = {
title: {
text: '访问比例',
top: '46%',
textAlign: 'center',
left: '30%',
textStyle: {
color: '#666',
fontSize: 18,
fontWeight: '400',
},
},
color: [
"#0195FD",
"#FF6364",
"#FECB01",
"#01FEFD",
"#90DFFE",
"#00CCFF"
],
tooltip: {
show: true,
formatter: '{b0}:{c0}%',
},
series: [
{
type: 'pie',
radius: ['60%', '75%'],
center: ['30%', '50%'],
hoverAnimation: true,
z: 10,
itemStyle: {
normal: {
borderWidth: 10,
borderColor: '#ffffff',
},
},
label: {
show: false,
},
data: chartData,
labelLine: {
show: false,
},
},
{
type: 'pie',
radius: ['50%', '58%'],
center: ['30%', '50%'],
hoverAnimation: true,
z: 10,
itemStyle: {
normal: {
borderWidth: 6,
borderColor: '#ffffff',
color: "#2F5573"
},
},
tooltip: {
show: false,
},
label: {
show: false,
},
data: dian_arr,
labelLine: {
show: false,
},
},
],
legend: {
type: 'scroll',
orient: 'horizontal',
data: legend_data,
right: 30,
top: '30%',
width: 200,
bottom: '30%',
align: 'left',
textStyle: {
color: '#333',
},
itemGap: 20,
formatter: (name) => {
let item = null;
for (const _item of chartData) {
if (_item.name === name) {
item = _item;
break;
}
}
if (item) {

return name + " " + parseInt(item.value * 100 / total) + "%";
} else {
return name;
}

},
},
};
this.chart.setOption(opts)
},
}
};
</script>

饼图 设置色值

image-20221006223227879

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from '@/assets/utils/chat_resize.js'

export default {
name: 'PieChart',
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: {
type: String,
default: ''
},
chartData: {
type: Array,
default: () => {
return [{
name: '甲',
value: 400,
color: '#3B6FDF'
}, {
name: '乙',
value: 100,
color: '#B783F2'
}, {
name: '丙',
value: 400,
color: '#7fa1eb'
}, {
name: '丁',
value: 200,
color: '#2dc58c'
}]
}
}
},
data () {
return {
chart: null
}
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted () {
await this.$nextTick()
this.initChart()
},
beforeDestroy () {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart () {
if (!this.chart) {
this.chart = echarts.init(this.$el)
}
const chartData = this.chartData || []
const legendData = []
let total = 0
for (const item of chartData) {
legendData.push(item.name)
total += item.value
}
const dianArr = []
for (let i = 0; i < 60; i++) {
dianArr.push(1)
}

const opts = {
title: {
text: this.$qianFunc(total),
top: '46%',
textAlign: 'center',
left: '50%',
textStyle: {
color: '#666',
fontSize: 18,
fontWeight: '800'
},
subtext: '(万元)',
subtextStyle: {}
},
tooltip: {
show: true,
formatter: '{b0}:{c0}'
},
series: [
{
type: 'pie',
radius: ['55%', '70%'],
center: ['50%', '50%'],
z: 10,
itemStyle: {
borderWidth: 0,
borderColor: '#ffffff',
color: function (para) {
return para.data.color
}
},
label: {
show: true,
position: 'outer',
alignTo: 'edge',
edgeDistance: 10
},
labelLine: {
show: true
},
data: chartData
},
{
type: 'pie',
radius: ['50%', '58%'],
center: ['50%', '50%'],
z: 10,
itemStyle: {
borderWidth: 6,
borderColor: '#ffffff',
color: '#2F5573'
},
tooltip: {
show: false
},
label: {
show: false
},
data: dianArr,
labelLine: {
show: false
}
}
],
legend: {
show: false,
type: 'plain',
orient: 'vertical',
data: legendData,
right: 30,
top: '30%',
width: 200,
bottom: '30%',
align: 'left',
textStyle: {
color: '#333'
},
itemGap: 20,
formatter: (name) => {
let item = null
for (const _item of chartData) {
if (_item.name === name) {
item = _item
break
}
}
if (item) {
return name + ' ' + parseInt(item.value * 100 / total) + '%'
} else {
return name
}
}
}
}
this.chart.setOption(opts)
}
}
}
</script>

主要设置了series[i].itemStyle.color

1
2
3
4
5
6
7
itemStyle: {
borderWidth: 0,
borderColor: '#ffffff',
color: function (para) {
return para.data.color
}
}

饼图 比例

image-20220509153234647

PieRateChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js"

export default {
name: "PieRateChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Number,
default: () => {
return 20
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function () {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let num = this.chartData;
let mydata = [{
name: "成功",
value: num
}, {
name: "失败",
value: 100 - num
}];
let opts = {
tooltip: {
show: true,
formatter: '{b0}: {c0}%',
},
color: ['#2A82E4', '#0BCDFE'],
series: [
{
type: 'pie',
radius: ['80%', '92%'],
center: ['50%', '50%'],
hoverAnimation: true,
data: mydata,
itemStyle: {
normal: {
borderWidth: 2,
borderColor: '#ffffff',
},
},
label: {
show: false,
position: 'center'
},
},
],
title: {
text: num + '%',
top: '42%',
textAlign: 'center',
left: '49%',
textStyle: {
color: '#666',
fontSize: 16,
fontWeight: '400',
},
},
};
this.chart.setOption(opts)
},
}
};
</script>

饼图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js";

export default {
name: "PieChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Array,
default: () => {
return [{
name: "春",
value: 400
}, {
name: "夏",
value: 100
}, {
name: "秋",
value: 200
}, {
name: "冬",
value: 500
}]
}
},
color:{
type: Array,
default: () => {
return [
"#0195FD",
"#FF6364",
"#FECB01",
"#01FEFD",
"#90DFFE",
"#00CCFF"
]
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let chartData = this.chartData || [];
let legend_data = [];
let total = 0;
for (const item of chartData) {
legend_data.push(item.name);
total += item.value;
}
let dian_arr = [];
for (let i = 0; i < 60; i++) {
dian_arr.push(1);
}

let opts = {
title: {
text: total,
top: '46%',
textAlign: 'center',
left: '39%',
textStyle: {
color: '#042871',
fontSize: 18,
fontWeight: '400',
},
},
color: this.color,
tooltip: {
show: true,
formatter: '{b0}:{c0}',
},
series: [
{
type: 'pie',
radius: ['30%', '80%'],
center: ['40%', '50%'],
roseType: 'radius',
hoverAnimation: true,
z: 10,
itemStyle: {
borderRadius: 5,

},
label: {
show: false,
},
data: chartData,
labelLine: {
show: false,
},
},

],
legend: {
type: 'plain',
orient: 'vertical',
data: legend_data,
right: 30,
top: '10%',
width: 200,
bottom: '10%',
align: 'left',
textStyle: {
color: '#333',
},
itemGap: 10,
formatter: (name) => {
let item = null;
for (const _item of chartData) {
if (_item.name === name) {
item = _item;
break;
}
}
return name;
},
},
};
this.chart.setOption(opts)
},
}
};
</script>

效果

image-20220918214448771

折线图

单折线

image-20221002162624735

代码

ZLineSingleChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from '@/assets/utils/chat_resize.js'

export default {
name: 'LineChart',
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
chartData: {
type: Array,
default: () => {
return [
{
name: "春",
value: 400,
},
{
name: "夏",
value: 100,
},
{
name: "秋",
value: 200,
},
{
name: "冬",
value: 500,
},
];
},
},
},
data() {
return {
chart: null
}
},
watch: {
chartData() {
this.initChart()
}
},
async mounted() {
await this.$nextTick()
this.initChart()
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el)
}

const chartData = this.chartData
const nameArr = chartData.map(item => item.name);
const valueArr = chartData.map(item => item.value);

const color = [
'#00CCFF',
'#0195FD',
'#FF6364'
]

const seriesArr = []
seriesArr.push(
{
data: valueArr,
type: 'line',
smooth: false,
symbol: 'circle',
symbolSize: 10,
animationDuration: 1600,
lineStyle: {
normal: {
color: '#00b3f4',
shadowColor: 'rgba(0, 0, 0, .3)',
shadowBlur: 0
}
},
label: {
show: true,
position: 'top',
textStyle: {
color: '#00b3f4'
}
},
itemStyle: {
color: '#00b3f4',
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0)',
shadowBlur: 0,
shadowOffsetY: 0,
shadowOffsetX: 0
},
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: color[0]
},
{
offset: 1,
color: '#ffffff'
}
])
}
}
)

const opts = {
color: color,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
show: true,
top: 2,
right: 10
},
xAxis: {
type: 'category',
data: nameArr
},
yAxis: {
type: 'value'
},
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true
},
series: seriesArr
}
this.chart.setOption(opts)
}
}
}
</script>

多折线图

image-20220510103846915

ZLinesChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from "echarts";
import resize from "@/assets/utils/chat_resize.js";

export default {
name: "ZLinesChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: "100%",
},
chartData: {
type: Object,
default: () => {
return {
groupNameArr: ["整体", "成功", "失败"],
nameArr: ["1月", "2月", "3月", "4月", "5月", "6月"],
valueArr: [[400, 300, 700, 350, 500, 350], [100, 200, 300, 50, 300, 50], [300, 100, 400, 300, 200, 300]],
}
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData(n, o) {
this.chartData = n
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}

let chartData = this.chartData
let groupNameArr = chartData.groupNameArr;
let nameArr = chartData.nameArr;
let valueArr = chartData.valueArr;

let color = [
"#00CCFF",
"#0195FD",
"#FF6364",
];

let seriesArr = [];
for (let i = 0; i < groupNameArr.length; i++) {
seriesArr.push(
{
name: groupNameArr[i],
data: valueArr[i],
type: 'line',
smooth: false,
symbol: false,
animationDuration: 1600,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: color[i]
},
{
offset: 1,
color: '#ffffff'
}
])
},
});
}

let opts = {
color: color,
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
legend: {
show: true,
top: 2,
right: 10
},
xAxis: {
type: 'category',
data: nameArr
},
yAxis: {
type: 'value'
},
grid: {
top: 40,
bottom: 20,
right: 10
},
series: seriesArr
};
this.chart.setOption(opts)
},
},
};
</script>

双Y轴

image-20221107235522087

代码

ZLinesY2Chart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from "echarts";
import resize from "@/components/charts/mixins/resize.js";

export default {
name: "ZLinesChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: "100%",
},
chartData: {
type: Array,
default: () => {
return [{
name: "01:10",
value1: 10,
value2: 100
}, {
name: "01:20",
value1: 2,
value2: 600
}, {
name: "01:30",
value1: 8,
value2: 200
}, {
name: "01:40",
value1: 3,
value2: 50
}]
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData(n, o) {
this.chartData = n
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}

let chartData = this.chartData
let nameArr = [];
let value1Arr = [];
let value2Arr = [];
for (let i = 0; i < chartData.length; i++) {
let item = chartData[i];
nameArr.push(item["name"]);
value1Arr.push(item["value1"]);
value2Arr.push(item["value2"]);
}

let color = [
"#6699ff",
"#41d2a1",
];

let seriesArr = [];
seriesArr.push(
{
data: value1Arr,
type: 'line',
smooth: true,
symbol: false,
animationDuration: 1600,
yAxisIndex: 0,
});

seriesArr.push(
{
data: value2Arr,
type: 'line',
smooth: true,
symbol: false,
animationDuration: 1600,
yAxisIndex: 1,
});

let opts = {
color: color,
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
legend: {
show: true,
top: 2,
right: 10
},
xAxis: {
type: 'category',
data: nameArr,
axisTick: {
show: false
}
},
yAxis: [
{
type: 'value',
splitLine: false
}, {
type: 'value',
splitLine: false
}
],
grid: {
top: 40,
bottom
:
20,
right
:
10,
containLabel
:
true
}
,
series: seriesArr
}
;
this.chart.setOption(opts)
},
},
};
</script>

柱状图

柱状图 环形

image-20220510125056553

BarPolarChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js"

export default {
name: "BarPolarChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: 0,
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Array,
default: () => {
return [{
name: "下游",
value: 60,
total: 100
}, {
name: "上游",
value: 10,
total: 50,
}, {
name: "集群",
value: 70,
total: 150
}]
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let chartData = this.chartData
let nameArr = [];
let valueArr = [];
let seriesData = [];
for (let i = 0; i < chartData.length; i++) {
let item = chartData[i];
nameArr.push(item.name);
valueArr.push(parseInt(item.value * 100 / item.total));
}
for (let i = 0; i < nameArr.length; i++) {
seriesData.push({
type: 'bar',
name: nameArr[i],
data: [valueArr[i]],
showBackground: true,
coordinateSystem: 'polar',
roundCap: false,
barGap: "120%"
})
}

let opts = {
color: [
"#01FEFD",
"#00CCFF",
"#096BCC",
"#FF6364",
"#FECB01",
"#00CCFF"
],
polar: {
radius: [10, '80%'],
},
angleAxis: {
max: 100,
startAngle: 270,
show: false,
},
radiusAxis: {
type: 'category',
show: false,
},
tooltip: {
show: true,
formatter: '{a0}: {c0}%',
},
series: seriesData,
legend: {
type: 'plain',
orient: 'horizontal',
data: nameArr,
right: "10%",
bottom: 10,
left: "10%",
align: 'left',
textStyle: {
color: '#333',
fontSize: 12
},
itemWidth: 12,
itemHeight: 12
},
};
this.chart.setOption(opts)
},
}
};
</script>

柱状体 单个

ZBarChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from '@/assets/utils/chat_resize.js'

export default {
name: 'BarChart',
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
title: {
type: String,
default: ''
},
chartData: {
type: Array,
default: () => {
return [
{ name: '1月', value: 400 },
{ name: '2月', value: 200 },
{ name: '3月', value: 300 },
{ name: '4月', value: 500 },
{ name: '5月', value: 100 },
{ name: '6月', value: 400 },
{ name: '7月', value: 300 },
{ name: '8月', value: 200 }
]
}
}
},
data () {
return {
chart: null
}
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted () {
await this.$nextTick()
this.initChart()
},
beforeDestroy () {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart () {
if (!this.chart) {
this.chart = echarts.init(this.$el)
}
const chartData = this.chartData
const nameArr = []
const valueArr = []
for (let i = 0; i < chartData.length; i++) {
const { name, value } = chartData[i]
nameArr.push(name)
valueArr.push(value)
}

const seriesArr = []
seriesArr.push({
type: 'bar',
data: valueArr,
barWidth: 16
})

const specialColor = {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{ offset: 0, color: '#46c6fe' }, { offset: 1, color: '#6fa0fa' }],
global: false // 缺省为 false
}
const opts = {
title: {
text: this.title,
top: 0,
textStyle: {
fontWeight: 'bold',
fontSize: 14
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
},
formatter: '{b}<br/>{a0}: {c0}<br />{a1}: {c1}'
},
legend: {
show: true,
top: 2,
right: 10
},
color: [
specialColor
],
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true
},
xAxis: [
{
type: 'category',
data: nameArr,
axisTick: {
alignWithLabel: true
},
axisLabel: {
rotate: 0
}
}
],
yAxis: [
{
type: 'value'
}
],
series: seriesArr
}
this.chart.setOption(opts)
}
}
}
</script>

柱状体 多个

image-20220510122613152

BarChart.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js";

export default {
name: "BarChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Object,
default: () => {
return {
groupNameArr: ["整体", "成功", "失败"],
nameArr: ["1月", "2月", "3月", "4月", "5月", "6月"],
valueArr: [[400, 300, 700, 350, 500, 350], [100, 200, 300, 50, 300, 50], [300, 100, 400, 300, 200, 300]],
}
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let chartData = this.chartData
let groupNameArr = chartData.groupNameArr;
let nameArr = chartData.nameArr;
let valueArr = chartData.valueArr;

let seriesArr = [];
for (let i = 0; i < groupNameArr.length; i++) {
seriesArr.push({
name: groupNameArr[i],
type: "bar",
data: valueArr[i],
});
}
let opts = {
title: {
text: this.title,
top: 0,
textStyle: {
fontWeight: 'bold',
fontSize: 14
}
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
formatter: '{b}<br/>{a0}: {c0}<br />{a1}: {c1}'
},
legend: {
show: true,
top: 2,
right: 10
},
color: [
"#00CCFF",
"#0195FD",
"#FF6364",
],
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true
},
xAxis: [
{
type: "category",
data: nameArr,
axisTick: {
alignWithLabel: true,
},
axisLabel: {
rotate: 0
}
},
],
yAxis: [
{
type: "value",
},
],
series: seriesArr
}
this.chart.setOption(opts)
},
}
};
</script>

柱状体 横向

image-20220509153409022

BarChartH.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from "@/assets/utils/chat_resize.js"

export default {
name: "BarChartH",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: 0,
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: ''
},
chartData: {
type: Object,
default: () => {
return {
nameArr: ["春", "夏", "秋", "冬"],
valueArr: [100, 200, 300, 50],
}
}
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function (n) {
this.initChart()
}
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}
let chartData = this.chartData
let nameArr = chartData.nameArr;
let valueArr = chartData.valueArr;
// 柱选中的颜色 渐变
let specialColor = {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: '#3c90f7', // 0% 处的颜色
},
{
offset: 1,
color: '#55bfc0', // 100% 处的颜色
},
],
globalCoord: false, // 缺省为 false
};
let opts = {
tooltip: {
show: true,
},
color: ['#2A82E4'],
xAxis: {
show: true,
color: '#f3f3f3',
},
yAxis: [
{
splitLine: 'none',
axisLine: 'none',
axisLabel: {
verticalAlign: 'middle',
align: 'right',
textStyle: {
color: '#666',
fontSize: '12',
},
width: 70,
overflow: 'breakAll'
},
data: nameArr,
},
],
series: [
{
type: 'bar',
showBackground: false,
data: valueArr,
barWidth: 16,
emphasis: {
itemStyle: {
color: specialColor,
},
},
},
],
grid: {
top: 40,
bottom: 10,
right: 10,
left: 10,
containLabel: true
},
dataZoom: {
right: '2%', //下滑块距离x轴底部的距离
top: '10%',
height: '90%', //下滑块手柄的高度调节
width: 20,
type: 'slider', //类型,滑动块插件
show: true, //是否显示下滑块
yAxisIndex: [0], //选择的y轴
start: 0, //初始数据显示多少
end: 100, //初始数据最多显示多少
},
};
this.chart.setOption(opts)
},
}
};
</script>

散点图

image-20221027125909516

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import * as echarts from "echarts";
import resize from "@/assets/utils/resize.js";

export default {
name: "ScatterChart",
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "100%",
},
title: {
type: String,
default: "",
},
chartData: {
type: Object,
default: () => {
return {
groupKey: "type",
nameKey: "name",
valueKey: "value",
list: [
{
name: "1月",
value: 3.3,
type: "春",
},
{
name: "1月",
value: 3.9,
type: "春",
},
{
name: "2月",
value: 5.3,
type: "春",
},
{
name: "3月",
value: 4.6,
type: "春",
},
{
name: "4月",
value: 5.0,
type: "春",
},
{
name: "5月",
value: 7.0,
type: "夏",
},
{
name: "6月",
value: 2.3,
type: "夏",
},
],
};
},
},
},
data() {
return {
chart: null,
};
},
watch: {
chartData: function () {
this.initChart();
},
},
async mounted() {
await this.$nextTick();
this.initChart();
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el);
}

let colors = [
["#6FFEFF", "#296AE8"],
["#FAD26B", "#F46839"],
];

let color_arr = [];
for (let i = 0; i < colors.length; i++) {
let specialColor = {
type: "scatter",
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: colors[i][0], // 0% 处的颜色
},
{
offset: 1,
color: colors[i][1], // 100% 处的颜色
},
],
globalCoord: false, // 缺省为 false
};
color_arr.push(specialColor);
}

let { groupKey, nameKey, valueKey, list } = this.chartData;
let nameArr = [];
let groupNameArr = [];
for (let i = 0; i < list.length; i++) {
let item = list[i];
if (nameArr.indexOf(item[nameKey]) === -1) {
nameArr.push(item[nameKey]);
}

if (groupNameArr.indexOf(item[groupKey]) === -1) {
groupNameArr.push(item[groupKey]);
}
}

let seriesArr = [];
for (let i = 0; i < groupNameArr.length; i++) {
let s = {
name: groupNameArr[i],
type: "scatter",
data: [],
};
for (let j = 0; j < list.length; j++) {
let item = list[j];
if (item[groupKey] === groupNameArr[i]) {
s.data.push([item[nameKey], item[valueKey]]);
}
}
if (i === 0) {
s.markLine = {
data: [
{
name: "一年期LPR",
xAxis: 0,
yAxis: 3.7,
label: {
formatter: "一年期LPR",
fontSize: "10",
},
lineStyle: {
normal: {
type: "dashed",
color: "#f59576",
},
},
},
{
name: "五年期LPR",
xAxis: 0,
yAxis: 4.65,
label: {
formatter: "五年期LPR",
fontSize: "10",
},
lineStyle: {
normal: {
type: "dashed",
color: "#00953f",
},
},
},
],
};
}
seriesArr.push(s);
}
let opts = {
title: {
text: this.title,
top: 0,
textStyle: {
fontWeight: "bold",
fontSize: 14,
},
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
formatter: "{b}: {c0}%",
},
legend: {
show: false,
bottom: 4,
x: "center",
},
color: color_arr,
grid: {
top: 20,
left: 10,
right: 60,
bottom: 10,
containLabel: true,
},
xAxis: [
{
type: "category",
data: nameArr,
axisTick: {
alignWithLabel: false,
},
axisLabel: {
rotate: 20,
},
},
],
yAxis: {
type: "value",
splitLine: false,
},
series: seriesArr,
};
this.chart.setOption(opts);
},
},
};
</script>

图形组合

image-20230326115723834

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<template>
<div :class="className" :style="{ height: height, width: width }"/>
</template>

<script>
import * as echarts from 'echarts'
import resize from '@/assets/utils/chat_resize.js'

export default {
name: 'ZBarSingleChart',
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
},
chartData: {
type: Array,
default: () => {
return [
{
name: "春",
value: 400,
},
{
name: "夏",
value: 100,
},
{
name: "秋",
value: 200,
},
{
name: "冬",
value: 500,
},
];
},
},
},
data() {
return {
chart: null
}
},
watch: {
chartData() {
this.initChart()
}
},
async mounted() {
await this.$nextTick()
this.initChart()
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(this.$el)
}

const chartData = this.chartData
const nameArr = chartData.map(item => item.name);
const valueArr = chartData.map(item => item.value);

const color = {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: '#04cef2', // 0% 处的颜色
},
{
offset: 1,
color: '#0287d7', // 100% 处的颜色
},
],
globalCoord: false, // 缺省为 false
}
const option = {
xAxis: [
{gridIndex: 0, type: 'category', show: false},
{gridIndex: 1, type: 'category', data: nameArr},
],
yAxis: [
{},
{gridIndex: 1}
],
legend: {
type: 'plain',
orient: 'horizontal',
data: nameArr,
bottom: 10,
align: 'left',
textStyle: {
color: '#333',
},
itemGap: 10,
},
grid: [
{left: 0, width: "40%", bottom: 140},
{left: '40%', bottom: 140}
],
series: [
// 这几个系列会出现在第一个直角坐标系中
{
type: 'pie', data: chartData,
label: {
show: false,
},
center: ['20%', '40%'],
labelLine: {
show: false,
},
radius: ['36%', '60%'],
},
// 这几个系列会出现在第二个直角坐标系中,
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1, data: valueArr, colorBy: "data"},
],
};
this.chart.setOption(option)
}
}
}
</script>

小技巧

Excel日期格式转字符串

有时我们想把Excel的数据转为JSON,但是日期格式获取的是数字,我们就要把数字改为文本。

1
= TEXT(A2,"yyyy-mm-dd")

金额格式化

方式1

1
2
3
4
5
6
7
8
Vue.prototype.$qianFunc = function (num) {
return (
num &&
parseFloat(num).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
return $1 + ','
})
)
};

方式2

1
2
3
Vue.prototype.$numFunc = function (num) {
return Number(num).toLocaleString()
};

科学计数法

在 JavaScript 中,可以使用 Number 对象的 toExponential() 方法将数字转换为科学计数法格式。该方法接受一个参数,表示指数的位数。

以下是一个示例:

1
2
3
let number = 123456789;
let scientific = number.toExponential(2);
console.log(scientific); // 输出 1.23e+8

在这个例子中,将数字 123456789 转换为科学计数法,指数的位数为 2,输出结果为 1.23e+8。

如果不指定指数的位数,则默认为 6 位。如果要将科学计数法格式的字符串转换回数字,可以使用 Number 对象的 parseFloat() 方法或 parseInt() 方法。例如:

1
2
3
let scientific = '1.23e+8';
let number = parseFloat(scientific);
console.log(number); // 输出 123000000

在这个例子中,将科学计数法格式的字符串 ‘1.23e+8’ 转换为数字,输出结果为 123000000。

1
2
3
export const kxnum = (value, digit) => {
return value.toExponential(digit);
};

数据处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
export const data4_1 = [
{
"name": "即期结汇",
"my": 2422020887,
"oy": 94000000
},
{
"name": "即期售汇",
"my": 5525874.39,
"oy": 21242336.49
},
{
"name": "远期结汇",
"my": 7409699544,
"oy": 633240000
},
{
"name": "外汇掉期",
"my": 95180000,
"oy": 51980000
},
{
"name": "外汇买卖",
"my": 75048795.44,
"oy": 282360256.9
},
{
"name": "新签约",
"my": 75048795.44,
"oy": 9117200.00
},
{
"name": "累计未到期",
"my": 80309451.47,
"oy": 1300000.00
}
];

export const data4_2 = {
groupNameArr: ["美元", "欧元"],
nameArr: data4_1.map(item => item.name),
valueArr: [
data4_1.map(item => item.my),
data4_1.map(item => item.oy)
],
};

表格滚动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<table class="mytable">
<tr>
<th>类型</th>
<th>小计</th>
<th>去年同期</th>
</tr>
<tbody class="scroll_table_body">
<tr v-for="(item, i) in data2_3_2" :key="i">
<td>{{ item.name }}</td>
<td>{{ item.yearnow }}</td>
<td>{{ item.yearlast }}</td>
</tr>
</tbody>
</table>

<script>
export default {
name: "HomeView",
components: {
},
data() {
return {

};
},
mounted() {
if (window.myInter) {
clearInterval(window.myInter);
}
window.myInter = setInterval(() => {
this.tableInterval();
}, 2000);
},
methods: {
change(table) {
var row = table.insertRow(table.rows.length); //在table的最后增加一行,table.rows.length是表格的总行数
for (let j = 0; j < table.rows[0].cells.length; j++) {
//循环第一行的所有单元格的数据,让其加到最后新加的一行数据中(注意下标是从0开始的)
var cell = row.insertCell(j); //给新插入的行中添加单元格
cell.innerHTML = table.rows[0].cells[j].innerHTML; //设置新单元格的内容,这个根据需要,自己设置
}
table.deleteRow(0); //删除table的第一行
},
tableInterval() {
let tables_arr = document.querySelectorAll(".scroll_table_body");
for (let i = 0; i < tables_arr.length; i++) {
this.change(tables_arr[i]);
}
},
},
};
</script>

<style lang="scss">
.mytable {
width: 100%;
padding-left: 5px;
padding-right: 5px;
tr {
th {
opacity: 0.6;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 1rem;
color: rgba(162, 251, 255, 0.8);
height: 2rem;
}

th:nth-child(1) {
text-align: left;
}

td {
font-family: MicrosoftYaHei;
font-size: 1rem;
color: #a4fbff;
line-height: 2rem;
height: 2rem;
}

td:nth-child(1) {
text-align: left;
}
}
}
</style>