/**
* 说明:
* el: 挂载的dom节点
* chartData 图表数据集合
* config 支持配置的文本,点击事件函数
* type 判断图表类型,有以下几个参数
* {
* ve-histogram 柱状图
* ve-finehistogram 柱状图+折线图
* ve-treemap 树形图
* ve-line 折线图
* }
*/
var chartTemplate =
`
`
window.proxy.vComponentChart = function (el, chartData, config, type) {
new Vue({
delimiters: ['${', '}'],
el: el,
template: chartTemplate,
data () {
return {
myChart: null,
type: type,
chartData: {},
// histogram 柱状图
histogramChart: {},
// barLineChart 柱状图+折线图
barLineChart: {},
// treeMapChart 树形图
treeMapChart: {},
// lineChart 折线图
lineChart: {}
}
},
created () {
this.chartData = chartData
this.getChartConfig()
},
mounted () {
if(this.type === 've-treemap') {
this.updateChartView()
} else if (this.type === 've-line') {
this.mergeExtendOptions()
}
},
methods: {
IsPC () {
var userAgentInfo = navigator.userAgent
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"]
var flagPc = true
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flagPc = false;
break;
}
}
return flagPc;
},
// 判断类型,取对应配置
getChartConfig () {
if (this.type === 've-histogram') {
this.histogramChart = {
options: {
colors: ['#FF9F3F', '#05A5F2'],
width: '100%',
height: '100%',
settings: {}
},
defaultOptions: {
grid: {
top: 20
},
xAxis: {
axisLabel: {
margin: 10,
interval: 1, // 强制显示x轴所有刻度
fontSize: 12
},
nameLocation: 'start',
nameTextStyle: {
fontSize: 12,
align: 'left',
padding: [70, 0, 0, 50],
color: '#9B9CA3'
}
},
yAxis (item) {
Object.assign(item[0], {
splitLine: {
lineStyle: {
type: 'dashed',
width: 0.5
}
},
axisLabel: {
margin: 2,
fontSize: 12,
formatter: (value, index) => value.toString().replace(/,/, '') + '%'
}
})
Object.assign(item[1], {
splitLine: {
show: false
},
axisLabel: {
show: false,
fontSize: 12,
formatter: (value, index) => value.toString().replace(/,/, '')
}
})
return item
},
tooltip: {
trigger: 'axis',
confine: true,
backgroundColor: '#fff',
axisPointer: {
type: 'shadow',
shadowStyle: {
color: 'rgba(42, 190, 209,0.1)'
},
z: 3
},
textStyle: {
color: '#171826',
fontSize: 12
},
padding: [7, 12],
extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)',
formatter: this.tooltipFormatter
},
legend: {
orient: 'horizontal',
icon: 'rect',
bottom: 20,
align: 'left',
itemGap: 20,
itemWidth: 9,
itemHeight: 9,
textStyle: {
fontSize: 10,
lineHeight: 14,
verticalAlign: 'bottom',
rich: {
a: {
fontSize: 16,
verticalAlign: 'top',
align: 'center',
padding: [0, 15, 28, 0]
},
b: {
fontSize: 14,
align: 'center',
padding: [0, 15, 0, 0],
lineHeight: 25
}
}
},
formatter: name => name
}
}
}
} else if (this.type === 've-finehistogram') {
this.barLineChart = {
options: {
height: '100%',
width: '100%',
colors: ['#05A6F3', '#FF3A20'],
settings: {
showLine: [chartData.columns[2]],
axisSite: { right: [chartData.columns[2]] }
},
config: this.newTimeConfig
},
defaultOptions: {
grid: {
top: 20
},
xAxis: {
axisLabel: {
margin: 10,
interval: 0, // 强制显示x轴所有刻度
fontSize: 12
},
nameLocation: 'start',
nameTextStyle: {
fontSize: 12,
align: 'left',
padding: [70, 0, 0, 50],
color: '#9B9CA3'
}
},
yAxis (item) {
item[0].splitLine = {
lineStyle: {
type: 'dashed',
width: 0.5
}
}
item[0].axisLabel = {
margin: 2,
fontSize: 12
}
item[1].splitLine = {
show: false
}
item[1].axisLabel = {
show: false,
fontSize: 12
}
item[0].axisLabel.formatter = (value, index) => {
return value.toString().replace(/,/, '')
}
item[1].axisLabel.formatter = (value, index) => {
return value.toString().replace(/,/, '')
}
return item
},
tooltip: {
trigger: 'axis',
confine: true,
backgroundColor: '#fff',
axisPointer: {
type: 'shadow',
shadowStyle: {
color: 'rgba(42, 190, 209,0.1)'
},
z: 3
},
textStyle: {
color: '#171826',
fontSize: 12
},
padding: [7, 12],
extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08);transform: translate3d(0,0,0)'
},
legend: {
orient: 'horizontal',
icon: 'circle',
bottom: 0,
align: 'left',
itemWidth: 8,
itemHeight: 8,
itemGap: 20,
textStyle: {
fontSize: 12,
rich: {
a: {
fontSize: 16,
verticalAlign: 'top',
align: 'center',
padding: [0, 15, 28, 0]
},
b: {
fontSize: 14,
align: 'center',
padding: [0, 15, 0, 0],
lineHeight: 25
}
}
},
formatter: (name) => {
if (name === '企业数量') {
name = name + '(个)'
}
return name
}
}
}
}
} else if (this.type === 've-treemap') {
this.treeMapChart = {
options: {
title: {
subtext: '单位:个、万元',
left: '0',
top: '-8px',
textStyle: {
color: '#000',
fontWeight: 'normal'
}
},
tooltip: {
formatter: this.treetooltipFormatter
}
},
defaultOptions: {
legend: {
show: true,
selectedMode: 'single',
data: [],
bottom: 0,
itemGap: 5
},
tooltip: {
backgroundColor: '#fff',
confine: true,
textStyle: {
color: '#171826',
fontSize: 12
},
padding: [7, 12],
extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
borderWidth: 2,
borderColor: '#F5F6F7'
},
series: [
{
type: 'treemap',
width: '100%',
// height: '85%',
// top: '15%',
roam: false, // 是否开启拖拽漫游(移动和缩放)
nodeClick: false, // 点击节点后的行为,false无反应
breadcrumb: {
show: false
},
label: { // 描述了每个矩形中,文本标签的样式。
normal: {
show: true,
position: ['10%', '40%']
}
},
itemStyle: {
normal: {
show: true,
textStyle: {
color: '#fff',
fontSize: 16
},
borderWidth: 1,
borderColor: '#fff'
},
emphasis: {
label: {
show: true
}
}
},
data: [
// {
// name: 'xxx',
// value: 122
// },
// {
// name: 'yyy',
// value: 122
// }
]
}
]
}
}
} else if (this.type === 've-line') {
let _this = this
this.lineChart = {
options: {
height: '100%',
colors: ['#05A6F3', '#FF9F40'],
config: this.configOptions
},
extend: {
yAxis: {
axisLabel: {
formatter: p => p + '%'
}
}
},
defaultOption: {
color: ['#05A6F3', '#FF9F40'],
xAxis: {
axisLabel: {
formatter: function (params) {
var arr = params.split('~')
var isPc = _this.IsPC()
if (arr.length === 2 && !isPc) {
return arr.join('\n-')
} else {
return params
}
},
textStyle: {
color: '#626262',
fontSize: 10
},
interval: 0
}
},
grid: {
top: 10,
left: 12,
right: 12
},
yAxis: {
splitLine: {
lineStyle: {
type: 'dashed',
width: 0.5
}
},
nameGap: 15,
nameTextStyle: {
fontSize: 12,
align: 'left',
color: '#9B9CA3',
padding: [0, 0, 0, -30]
},
axisLabel: {
margin: 2,
fontSize: 12,
color: '#5F5E64',
interval: 'auto',
formatter: (value, index) => {
return value.toString().replace(/,/, '')
}
}
},
legend: {
orient: 'horizontal',
icon: 'circle',
bottom: 10,
itemWidth: 8,
itemHeight: 8,
itemGap: 40,
textStyle: {
color: '#5F5E64',
fontSize: 12
}
},
series: {
type: 'line',
showSymbol: false,
smooth: false,
symbol: 'circle',
symbolSize: 3,
itemStyle: {
borderColor: '#fff',
borderWidth: 1
}
},
tooltip: {
backgroundColor: '#fff',
confine: true,
axisPointer: {
type: 'line',
lineStyle: {
width: 2,
color: '#2ABED1'
},
z: 3
},
textStyle: {
color: '#171826',
fontSize: 12
},
padding: [7, 12],
extraCssText: 'box-shadow: 0px 4px 16px rgba(8, 31, 38, 0.08)',
borderWidth: 2,
borderColor: '#F5F6F7'
},
lineStyle: {
width: 0.5
}
}
}
}
},
// S--histogram--S
extend (chart) {
chart.setOption({
series: [
{
type: 'bar',
barMaxWidth: 20
},
{
type: 'bar',
barMaxWidth: 20
}
]
})
},
tooltipFormatter (params) {
let tip = `
${params[0].name}
`
for (let i = 0; i < params.length; i++) {
if (params[i].value === undefined || params[i].value === '') {
params[i].value = 0
}
if (i === 0) {
tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%
'
} else if (i === 1) {
tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%
'
}
}
return tip
},
// E--histogram--E
// S--barLineChart--S
barExtend (chart) {
chart.setOption({
series: [{
type: 'bar',
barMaxWidth: 20
}, {
type: 'line',
smooth: false,
symbol: 'none'
}]
})
},
newTimeConfig (options) {
options.xAxis[0].axisLabel.rotate = 60
options.xAxis[0].axisLabel.interval = 'auto'
options.yAxis[1].axisLabel.show = true
if (this.chartData.rows.length > 12) {
// 设置时间轴
Object.assign(options, {
// grid解决dataZoom文字被隐藏的问题
// https://github.com/apache/echarts/issues/11601
grid: {
left: '5%',
right: '13%'
},
dataZoom: {
show: true, // 显示滚动条
realtime: true, // 拖动时,是否实时更新系列的视图
type: 'slider',
height: 20,
bottom: 0,
textStyle: {
fontSize: 10
}
}
})
}
options.legend.bottom = 30
options.legend.data = [
{ icon: 'rect', name: this.chartData.columns[1] },
{ icon: 'line', name: this.chartData.columns[2] }
]
options.tooltip.axisPointer.shadowStyle.color = 'rgba(5,166,243,0.1)'
options.tooltip.formatter = params => {
let tip = `${params[0].name}
`
for (let i = 0; i < params.length; i++) {
if (params[i].value === undefined || params[i].value === '') {
params[i].value = 0
}
if (params[i].seriesName.indexOf('环比') === -1) {
const match = params[i].seriesName.match(/((.*))$/g)
let unit = ''
if (Array.isArray(match)) {
unit = match.join('').replace(/[()]/g, '')
}
tip = tip + params[i].marker + params[i].seriesName.replace(`(${unit})`, '') + ':' + params[i].value + unit + '
'
} else {
tip = tip + params[i].marker + params[i].seriesName + ':' + params[i].value + '%' + '
'
}
}
return tip
}
return options
},
// E--barLineChart--E
// S--treeMapChart--S
updateChartView () {
this.myChart = echarts.init(this.$el, 'light')
if (!this.myChart) return
this.mergeOptions()
this.myChart.setOption(this.treeMapChart.defaultOptions)
window.addEventListener('resize', () => {
// this.myChart.resize()
})
},
mergeOptions () {
// 设置数据
this.treeMapChart.defaultOptions.series[0].data = this.chartData
// 设置图例?
this.treeMapChart.defaultOptions.legend.data = this.chartData.map(item => {
return item.name
})
_.merge(this.treeMapChart.defaultOptions, this.treeMapChart.options)
},
treetooltipFormatter (params) {
const item = params.data
let tip = `${params.name}
`
if (item && item.value) {
tip += `项目数量:${item.value}个
`
}
if (item && item.amount) {
tip += `
项目金额:${item.amount}万元
`
}
return tip
},
// E--treeMapChart--E
// S--lineChart--S
configOptions (options) {
// 面积颜色-渐变
Object.assign(options.series[0], {
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(42, 190, 209, 0.12)'
},
{
offset: 1,
color: 'rgba(42, 190, 209, 0)'
}
], false)
}
}
})
Object.assign(options.series[1], {
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(255, 159, 63, 0.12)'
},
{
offset: 1,
color: 'rgba(255, 159, 63, 0)'
}
], false)
}
}
})
Object.assign(options.legend, {
icon: 'rect'
})
options.tooltip.formatter = params => {
let tip = `
${params[0].name}
`
for (let i = 0; i < params.length; i++) {
params[i].marker = '
'
tip += params[i].marker + params[i].seriesName + ':' + params[i].value[1].toString().replace(/,/, '') + '%' + '
'
}
return tip
}
return options
},
mergeExtendOptions () {
_.merge(this.lineChart.defaultOption, this.lineChart.extend)
}
// E--lineChart--E
}
})
}