封装一个折线图组件 发表于 2024-07-13 最近因为工作需要,封装了一个折线图组件。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439<template> <!-- 左侧图标区 --> <div ref="lineChart" id="charts"></div></template><script> import * as echarts from 'echarts' import { deepMerge, hexToRgb } from '@/utils/index' export default { name: 'CgLineChart', data() { return { selectIndex: 4, defaultOptions: {}, chartInstance: null, xAxisName: '区/县', yAxisName: '总数', xAxisData: [ '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月', ], colors: ['#9D2932', '#789262', '#494166', '#D9B612', '#177CB0'], } }, props: { chartOptions: { type: Object, default: () => ({}), }, }, methods: { handleResize() { if (this.chartInstance) { this.chartInstance.resize() } }, // 初始化echarts initChart() { const chartContainer = this.$refs.lineChart this.chartInstance = echarts.init(chartContainer) this.updateChart() }, // 生成渐变背景色的折线图 generateColorOptions() { const colors = this.chartOptions.colors ? this.chartOptions.colors : this.colors const options = { tooltip: { show: true, trigger: 'axis', backgroundColor: '#000342', textStyle: { color: '#fff', }, }, xAxis: { type: 'category', name: this.chartOptions.xAxisName ? this.chartOptions.xAxisName : this.xAxisName, axisLabel: { fontSize: 14, margin: 20, }, axisLine: { show: true, onZero: false, lineStyle: { color: '#1d97cf', }, }, axisTick: { show: true, length: 9, alignWithLabel: true, lineStyle: { color: '#1d97cf', }, }, data: this.chartOptions.xAxisData || this.xAxisData, }, yAxis: { type: 'value', name: this.chartOptions.yAxisName ? this.chartOptions.yAxisName + ' ' : this.yAxisName + ' ', axisLine: { show: true, lineStyle: { color: '#1d97cf', }, }, splitLine: { show: true, lineStyle: { color: '#153d7d', type: 'dashed', }, }, axisTick: { show: true, inside: true, length: 10, }, axisLabel: { show: true, interval: 'auto', formatter: '{value}', }, }, legend: { icon: 'rect', itemGap: 80, top: '3%', textStyle: { color: '#FFF', }, data: this.chartOptions.chartData.map((item) => item.name), }, series: this.chartOptions.chartData.map((item, index) => { return { name: item.name, data: item.value, type: 'line', smooth: true, symbol: 'circle', symbolSize: 5, showSymbol: false, lineStyle: { normal: { width: 2, color: colors[index], }, }, areaStyle: { normal: { color: new echarts.graphic.LinearGradient( 0, 0, 0, 1, [ { offset: 0, color: `${hexToRgb(colors[index], 0.7)}`, }, { offset: 0.5, color: `${hexToRgb(colors[index], 0.4)}`, }, { offset: 0.8, color: `${hexToRgb(colors[index], 0.1)}`, }, ], false ), shadowColor: `${hexToRgb(colors[index], 0.1)}`, shadowBlur: 10, }, }, itemStyle: { normal: { color: colors[index], }, }, } }), } return options }, generateDefaultOptions() { const series = [] const colors = this.chartOptions.colors ? this.chartOptions.colors : this.colors const selectIndex = this.chartOptions.selectIndex || this.selectIndex this.chartOptions.chartData.forEach((item, index) => { series.push({ name: item.name, data: item.value.map((innerItem) => innerItem.num), type: 'line', smooth: true, symbolSize: 8, showSymbol: true, lineStyle: { normal: { color: colors[index], width: 2, type: 'solid', }, }, itemStyle: { normal: { color: colors[index], borderColor: colors[index], shadowColor: colors[index], shadowBlur: 20, borderWidth: 3, }, }, }) if (this.chartOptions.isAnimation) { series.push({ // 设置涟漪特效动画 type: 'effectScatter', data: [ { value: [ item.value[selectIndex].time, item.value[selectIndex].num, ], symbolSize: 8, }, ], //2d坐标系--[x轴, y轴, 标记大小] showEffectOn: 'render', // 涟漪特效配置 rippleEffect: { // 波纹的绘制方式,可选'stroke'和'fill' brushType: 'stroke', period: 2, //动画的时间。 scale: 3.5, //动画中波纹的最大缩放比例。 }, hoverAnimation: true, itemStyle: { normal: { color: '#f5f503', shadowBlur: 20, shadowColor: '#fff', }, }, zlevel: 1, }) } // series.push( // { // name: item.name, // data: item.value.map((innerItem) => innerItem.num), // type: "line", // smooth: true, // symbolSize: 8, // showSymbol: true, // lineStyle: { // normal: { // color: colors[index], // width: 2, // type: "solid", // }, // }, // itemStyle: { // normal: { // color: colors[index], // borderColor: colors[index], // shadowColor: colors[index], // shadowBlur: 20, // borderWidth: 3, // }, // }, // }, // { // // 设置涟漪特效动画 // type: "effectScatter", // data: [ // { // value: [ // item.value[selectIndex].time, // item.value[selectIndex].num, // ], // symbolSize: 8, // }, // ], //2d坐标系--[x轴, y轴, 标记大小] // showEffectOn: "render", // // 涟漪特效配置 // rippleEffect: { // // 波纹的绘制方式,可选'stroke'和'fill' // brushType: "stroke", // period: 2, //动画的时间。 // scale: 3.5, //动画中波纹的最大缩放比例。 // }, // hoverAnimation: true, // itemStyle: { // normal: { // color: "#f5f503", // shadowBlur: 20, // shadowColor: "#fff", // }, // }, // zlevel: 1, // } // ); }) const options = { tooltip: { show: true, trigger: 'axis', backgroundColor: '#000342', textStyle: { color: '#fff', }, }, xAxis: { type: 'category', name: this.chartOptions.xAxisName ? this.chartOptions.xAxisName : this.xAxisName, axisLabel: { fontSize: 14, margin: 20, }, axisLine: { show: true, onZero: false, lineStyle: { color: '#1d97cf', }, }, axisTick: { show: true, length: 9, alignWithLabel: true, lineStyle: { color: '#1d97cf', }, }, data: this.chartOptions.xAxisData || this.xAxisData, }, yAxis: { type: 'value', name: this.chartOptions.yAxisName ? this.chartOptions.yAxisName + ' ' : this.yAxisName + ' ', axisLine: { show: true, lineStyle: { color: '#1d97cf', }, }, splitLine: { show: true, lineStyle: { color: '#153d7d', type: 'dashed', }, }, axisTick: { show: true, inside: true, length: 10, }, axisLabel: { show: true, interval: 'auto', formatter: '{value}', }, }, legend: { icon: 'rect', itemGap: 80, top: '3%', textStyle: { color: '#FFF', }, data: this.chartOptions.chartData.map((item) => item.name), }, series: series, } return options }, // 生成配置项 generateChartOption() { let options = {} if (!this.chartOptions.type) { const defaultOptions = this.generateDefaultOptions() options = defaultOptions } if (this.chartOptions.type === 'gradation') { const colorOptions = this.generateColorOptions() options = colorOptions } else if (this.chartOptions.type === 'default') { const defaultOptions = this.generateDefaultOptions() options = defaultOptions } this.defaultOptions = options const mergedOptions = deepMerge({}, this.defaultOptions) const res = deepMerge( mergedOptions, this.chartOptions.echartOptions || {} ) return res }, // 更新图表 updateChart() { const option = this.generateChartOption() this.chartInstance.setOption(option, true) }, }, mounted() { window.addEventListener('resize', this.handleResize) this.initChart() }, beforeDestroy() { window.removeEventListener('resize', this.handleResize) if (this.chartInstance) { this.chartInstance.dispose() } }, watch: { chartOptions: { deep: true, handler() { this.updateChart() }, }, }, }</script><!-- Add "scoped" attribute to limit CSS to this component only --><style lang="scss" scoped> #charts { width: 100%; height: 100%; margin: 0 auto; }</style>