能简单支持基础柱状图单系列、多系列、堆叠图、饼图、环形图
主题文件
export const universalTheme = {
width: 'auto',
height: 'auto',
color: [
'#4e83fd',
'#50cefb',
'#935af6',
'#fad355',
'#f76964',
'#ffa53d',
'#4ea397',
'#22c3aa',
'#7bd9a5',
'#d0648a',
'#f58db2',
'#f2b3c9',
'#82a3f0',
'#7ed1ef',
'#a982eb',
],
backgroundColor: 'rgba(255,255,255,0)',
textStyle: {},
title: {
textStyle: {
color: '#000000'
},
subtextStyle: {
color: '#675e5e'
}
},
line: {
itemStyle: {
borderWidth: '2'
},
lineStyle: {
width: '2'
},
symbolSize: '8',
symbol: 'emptyCircle',
smooth: false
},
radar: {
itemStyle: {
borderWidth: '2'
},
lineStyle: {
width: '2'
},
symbolSize: '8',
symbol: 'emptyCircle',
smooth: false
},
bar: {
itemStyle: {
barBorderWidth: '0',
barBorderColor: '#eeeeee'
}
},
pie: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
scatter: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
boxplot: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
parallel: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
sankey: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
funnel: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
gauge: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
}
},
candlestick: {
itemStyle: {
color: '#e44d7d',
color0: 'transparent',
borderColor: '#d0648a',
borderColor0: '#22c3aa',
borderWidth: '1'
}
},
graph: {
itemStyle: {
borderWidth: '0',
borderColor: '#eeeeee'
},
lineStyle: {
width: '1',
color: '#4e83fd'
},
symbolSize: '8',
symbol: 'emptyCircle',
smooth: false,
color: [
'#4e83fd',
'#50cefb',
'#935af6',
'#fad355',
'#f76964',
'#ffa53d',
'#4ea397',
'#22c3aa',
'#7bd9a5',
'#d0648a',
'#f58db2',
'#f2b3c9',
'#82a3f0',
'#7ed1ef',
'#a982eb',
],
label: {
color: '#ffffff'
}
},
map: {
itemStyle: {
areaColor: '#eeeeee',
borderColor: '#999999',
borderWidth: 0.5
},
label: {
color: '#28544e'
},
emphasis: {
itemStyle: {
areaColor: 'rgba(34,195,170,0.25)',
borderColor: '#22c3aa',
borderWidth: 1
},
label: {
color: '#349e8e'
}
}
},
geo: {
itemStyle: {
areaColor: '#eeeeee',
borderColor: '#999999',
borderWidth: 0.5
},
label: {
color: '#28544e'
},
emphasis: {
itemStyle: {
areaColor: 'rgba(34,195,170,0.25)',
borderColor: '#22c3aa',
borderWidth: 1
},
label: {
color: '#349e8e'
}
}
},
categoryAxis: {
axisLine: {
show: false,
lineStyle: {
// 控制鼠标一到图标上x轴坐标显示的字体颜色
color: '#cccccc'
}
},
axisTick: {
show: true,
lineStyle: {
// 横坐标轴刻度的颜色
color: '#eeeeee'
}
},
axisLabel: {
show: true,
// 横坐标字体默认的颜色
color: '#999999'
},
splitLine: {
// 坐标系中的竖线样式控制
show: false,
lineStyle: {
color: [
'#eeeeee'
]
}
},
splitArea: {
// 坐标系被竖线分割为几份后,每份区间的背景色等控制
show: false,
areaStyle: {
color: [
'rgba(250,250,250,0.05)',
'rgba(200,200,200,0.02)'
]
}
}
},
valueAxis: {
axisLine: {
// y轴样式控制
show: true,
lineStyle: {
color: '#eeeeee'
}
},
axisTick: {
// y轴刻度线样式控制
show: false,
lineStyle: {
color: '#333'
}
},
axisLabel: {
// y轴字体样式控制
show: true,
color: '#999999'
},
splitLine: {
// 坐标系中的横线样式控制
show: true,
lineStyle: {
color: [
'#eeeeee'
]
}
},
splitArea: {
show: false,
areaStyle: {
color: [
'rgba(250,250,250,0.05)',
'rgba(200,200,200,0.02)'
]
}
}
},
logAxis: {
axisLine: {
show: true,
lineStyle: {
color: '#eeeeee'
}
},
axisTick: {
show: false,
lineStyle: {
color: '#333'
}
},
axisLabel: {
show: true,
color: '#999999'
},
splitLine: {
show: true,
lineStyle: {
color: [
'#eeeeee'
]
}
},
splitArea: {
show: false,
areaStyle: {
color: [
'rgba(250,250,250,0.05)',
'rgba(200,200,200,0.02)'
]
}
}
},
timeAxis: {
axisLine: {
show: true,
lineStyle: {
color: '#eeeeee'
}
},
axisTick: {
show: false,
lineStyle: {
color: '#333'
}
},
axisLabel: {
show: true,
color: '#999999'
},
splitLine: {
show: true,
lineStyle: {
color: [
'#eeeeee'
]
}
},
splitArea: {
show: false,
areaStyle: {
color: [
'rgba(250,250,250,0.05)',
'rgba(200,200,200,0.02)'
]
}
}
},
toolbox: {
iconStyle: {
borderColor: '#999999'
},
emphasis: {
iconStyle: {
borderColor: '#666666'
}
}
},
legend: {
textStyle: {
color: '#999999'
}
},
tooltip: {
axisPointer: {
lineStyle: {
color: '#cccccc',
width: 1
},
crossStyle: {
color: '#cccccc',
width: 1
}
}
},
timeline: {
lineStyle: {
color: '#4e83fd',
width: 1
},
itemStyle: {
color: '#4e83fd',
borderWidth: 1
},
controlStyle: {
color: '#4e83fd',
borderColor: '#4e83fd',
borderWidth: 0.5
},
checkpointStyle: {
color: '#4e83fd',
borderColor: '#f5f5f5'
},
label: {
color: '#4e83fd'
},
emphasis: {
itemStyle: {
color: '#4e83fd'
},
controlStyle: {
color: '#4e83fd',
borderColor: '#4e83fd',
borderWidth: 0.5
},
label: {
color: '#4e83fd'
}
}
},
visualMap: {
color: [
'#d0648a',
'#22c3aa',
'#adfff1'
]
},
dataZoom: {
backgroundColor: 'rgba(255,255,255,0)',
dataBackgroundColor: 'rgba(222,222,222,1)',
fillerColor: 'rgba(114,230,212,0.25)',
handleColor: '#cccccc',
handleSize: '100%',
textStyle: {
color: '#999999'
}
},
markPoint: {
label: {
color: '#ffffff'
},
emphasis: {
label: {
color: '#ffffff'
}
}
}
}
通用组件
<!-- 图表容器 -->
<template>
<div
class="chart-container"
ref="charts"
:style="{
width: chartParentWidth
}"
></div>
</template>
<script>
import * as echarts from 'echarts'
import { universalTheme } from './universal.js'
// console.log('universalThemeuniversalTheme', universalTheme)
export default {
name: 'universalChartComponent',
props: {
// 图表的宽度
chartParentWidth: {
type: String,
default: '100%'
},
// 标题
title: {
type: String,
default: ''
},
// 图表类型
seriesType: {
type: String,
default: ''
},
//数据集
dimensions: {
type: Array,
default: () => {
return []
}
},
source: {
type: Array,
default: () => {
return []
}
},
// 是否为推叠图
isStack: {
type: Boolean,
default: false
},
// 是否为环形图
isAnnular: {
type: Boolean,
default: false
}
},
computed: {
// 是否为多系列
isMultiSeries() {
if (this.dimensions > 2) {
return true
} else {
return false
}
}
},
data() {
return {
charts: echarts,
myCharts: null, // 当前图表实例
baseOption: {
dataset: [
{
// dimensions: this.dimensions,
source: [this.dimensions, ...this.source]
}
],
// 基础配置
legend: {
type: 'scroll',
width: '70%',
align: 'right',
itemWidth: 15,
itemHeight: 15,
itemGap: 11
},
grid: {
// 包含文本
// left:'left',
containLabel: true
},
toolbox: {
show: true,
right: '30px',
feature: {
dataView: {
// show:this.dataViewShow||false,
show: false,
readOnly: false,
title: '列表视图',
width: '110%',
lang: [
'<div style="padding: 0 10px;margin-top:-18px;margin-left:-28px;background:#fff;">数据列表</div>',
`<div style="
position: absolute;
top: -25px;
background: #1890ff;
right: 22px;
width: 59px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
font-size: 12px;
z-index: 99999999;
letter-spacing: 4px;
">关闭</div>`,
'<div style="background:#fff;position: absolute;top: 0;right: 0;z-index: 333;width: 30px;" @click="javascrupt:;">刷新</div>'
],
buttonColor: '#1890ff',
buttonTextColor: '#fff',
optionToContent: opt => {
var axisData = opt.xAxis[0].data || opt.yAxis[0].data //x轴作为条件,y轴需改成yAxis[0].data;
var series = opt.series
var tdHeads = '<th style="padding:0 10px;height:30px;background-color: #eeeeee;">名称</th>'
series.forEach(function(item) {
tdHeads += '<th style="padding: 0 10px;height:30px;background-color: #eeeeee;">' + item.name + '</th>'
})
var table =
'<table class="data-view-table" border="1" style="height:100%;width:100%;border-collapse:collapse;font-size:14px;text-align:center"><thead><tr>' +
tdHeads +
'</tr></thead><tbody>'
var tdBodys = ''
for (var i = 0, l = axisData.length; i < l; i++) {
for (var 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 style="height: 30px;"><td style="padding: 0 10px">' + axisData[i] + '</td>' + tdBodys + '</tr>'
tdBodys = ''
}
table += '</tbody></table>'
return table
}
},
magicType: (() => {
if (this.seriesType !== 'pie') {
return {
type: ['line', 'bar'],
title: {
line: '折线图切换',
bar: '柱形图切换'
}
}
} else {
return {}
}
})()
}
},
dataZoom: []
},
barLine: {
series: (() => {
// [{ type: this.seriesType }]
let dimensions = [...this.dimensions]
let colName = dimensions.shift()
let result = []
let stack = ''
if (this.isStack) {
stack = 'total'
}
dimensions.map((element, index) => {
result.push({
type: this.seriesType,
stack: stack || element,
barMaxWidth: 30, // 柱子宽度smooth: true,
showAllSymbol: true, //显示所有图形。
// symbol: 'circle', //标记的图形为实心圆
symbolSize: 8, //标记的大小
universalTransition: true,
animationDurationUpdate: 1000,
label: {
show: true
// position: 'inside',
}
})
})
return result
})(),
// / 声明一个 X 轴,类目轴(category)。默认情况下,类目轴对应到 dataset 第一列。
xAxis: { type: 'category' },
// 声明一个 Y 轴,数值轴。
yAxis: {},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(1, 13, 19, 0.5)',
order: 'valueDesc',
axisPointer: {
type: this.packetPolymerization ? 'shadow' : 'cross',
crossStyle: {
color: '#666',
type: 'dashed'
}
},
formatter: datas => {
let outHtml = `<div style="
display: flex;
flex-wrap: wrap;
max-width:${datas.length > 20 ? ' 900px' : '150px'};
max-height: 400px;
overflow: hidden;
"><div style="width:100%;">${datas[0].name || ''}</div>`
datas.map((element, index) => {
let dataItem = [...element.value]
dataItem.shift()
// console.log('dataItem--------', dataItem)
let divStr = `<div class="formatter" style="display:inline-block;margin-right:10px;">
<div>
${element.marker} <span class="label">${element.seriesName}:</span>
<span class="cont">${dataItem[index]}</span>
</div>
</div>`
outHtml += divStr
})
outHtml += '</div>'
return outHtml
}
}
},
pie: {
tooltip: {
trigger: 'item'
},
legend: (() => {
return {
type: 'scroll',
orient: 'vertical',
height: '80%',
right: '27px',
top: 'center',
itemWidth: 15,
itemHeight: 15,
itemGap: 11,
formatter: name => {
let total = 0
this.source.map(element => {
total += element[1]
})
for (var i = 0; i < this.source.length; i++) {
if (name == this.source[i][0]) {
let persent = 0
if (total != 0) {
persent = ((this.source[i][1] / total) * 100).toFixed(2)
}
return `${name}:${this.dimensions[1]}为${this.source[i][1]}, 占比为${persent}%`
}
}
}
}
})(),
series: (() => {
return [
{
type: 'pie',
radius: (() => {
if (this.isAnnular) {
return ['25%', '45%']
} else {
return '50%'
}
})(),
center: ['30%', '50%'],
label: {
fontSize: 12
}
}
]
})()
}
}
},
mounted() {
this.$refs['charts'].innerHTML = ''
// 注册并使用主题
this.charts.registerTheme('universalTheme', universalTheme)
this.myCharts = this.charts.init(this.$refs['charts'], 'universalTheme')
this.$nextTick(() => {
this.init()
})
window.addEventListener('resize', () => {
this.myCharts && this.myCharts.resize()
})
},
methods: {
showLoading(text = '加载中,请稍候...') {
this.myCharts.showLoading({ text, color: '#1890ff', textColor: '#1890ff' })
},
hideLoading() {
this.myCharts.hideLoading()
},
init() {
this.showLoading()
setTimeout(() => {
let option = {}
if (this.seriesType == 'bar' || this.seriesType == 'line') {
option = Object.assign(this.baseOption, this['barLine'])
}
if (this.seriesType == 'pie') {
option = Object.assign(this.baseOption, this['pie'])
}
this.myCharts.setOption(option, true)
console.log('universal---------', option, this.myCharts)
this.myCharts && this.myCharts.resize()
this.hideLoading()
this.myCharts.on('click', params => {
this.$emit('onClickHandle', params)
})
}, 10)
}
}
}
</script>
<style lang="scss" scoped>
.chart-container {
height: 700px;
}
</style>
组件使用
<universal-chart
v-if="index == 1 && !loading"
key="diy_x1"
title="多系列折线图"
seriesType="line"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>
<universal-chart
v-if="index == 1 && !loading"
key="diy_x"
title="多系列柱状图"
seriesType="bar"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>
<universal-chart
v-if="index == 1 && !loading"
key="diy_x2"
title="堆叠柱状图"
seriesType="bar"
:isStack="true"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>
<universal-chart
v-if="index == 3 && !loading"
key="diy_x0"
title="基础柱状图"
seriesType="bar"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>
<!-- 饼图 -->
<universal-chart
v-if="index == 3 && !loading"
key="diy_x0"
title="基础饼图"
seriesType="pie"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>
<!-- 饼图 -->
<universal-chart
v-if="index == 3 && !loading"
key="diy_x02"
title="基础环形图"
seriesType="pie"
:isAnnular="true"
:dimensions="item.dimensions"
:source="item.source"
></universal-chart>