/** * 说明: * 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 } }) }