vue echarts图表组建封装,实现折线图饼图联动
基于vue封装的柱状图,饼图,条形图,以及折线图饼图联动
效果展示
详细代码如下
折线图组件
<template> <div :class="className" :style="{height:height,width:width}" /> </template> <script> import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize' export default { mixins: [resize], props: { className: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '350px' }, autoResize: { type: Boolean, default: true }, chartData: { type: Object, required: true } }, data() { return { chart: null } }, watch: { chartData: { deep: true, handler(val) { this.setOptions(val) } } }, mounted() { this.$nextTick(() => { this.initChart() }) }, beforeDestroy() { if (!this.chart) { return } this.chart.dispose() this.chart = null }, methods: { initChart() { this.chart = echarts.init(this.$el, 'macarons') this.setOptions(this.chartData) }, setOptions({ expectedData, actualData } = {}) { this.chart.setOption({ xAxis: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], boundaryGap: false, axisTick: { show: false } }, grid: { left: 10, right: 10, bottom: 20, top: 30, containLabel: true }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' }, padding: [5, 10] }, yAxis: { axisTick: { show: false } }, legend: { data: ['expected', 'actual'] }, series: [{ name: 'expected', itemStyle: { normal: { color: '#FF005A', lineStyle: { color: '#FF005A', width: 2 } } }, smooth: true, type: 'line', data: expectedData, animationDuration: 2800, animationEasing: 'cubicInOut' }, { name: 'actual', smooth: true, type: 'line', itemStyle: { normal: { color: '#3888fa', lineStyle: { color: '#3888fa', width: 2 }, areaStyle: { color: '#f3f8ff' } } }, data: actualData, animationDuration: 2800, animationEasing: 'quadraticOut' }] }) } } } </script>
饼图组件
<template> <div :class="className" :style="{height:height,width:width}" /> </template> <script> import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize' export default { mixins: [resize], props: { className: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '300px' } }, data() { return { chart: null } }, mounted() { this.$nextTick(() => { this.initChart() }) }, beforeDestroy() { if (!this.chart) { return } this.chart.dispose() this.chart = null }, methods: { initChart() { this.chart = echarts.init(this.$el, 'macarons') this.chart.setOption({ tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} ({d}%)' }, legend: { left: 'center', bottom: '10', data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts'] }, series: [ { name: 'WEEKLY WRITE ARTICLES', type: 'pie', roseType: 'radius', radius: [15, 95], center: ['50%', '38%'], data: [ { value: 320, name: 'Industries' }, { value: 240, name: 'Technology' }, { value: 149, name: 'Forex' }, { value: 100, name: 'Gold' }, { value: 59, name: 'Forecasts' } ], animationEasing: 'cubicInOut', animationDuration: 2600 } ] }) } } } </script>
面板组件
<template> <el-row :gutter="40" class="panel-group"> <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="card-panel" @click="handleSetLineChartData('newVisitis')"> <div class="card-panel-icon-wrapper icon-people"> <svg-icon icon-class="peoples" class-name="card-panel-icon" /> </div> <div class="card-panel-description"> <div class="card-panel-text"> New Visits </div> <count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" /> </div> </div> </el-col> <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="card-panel" @click="handleSetLineChartData('messages')"> <div class="card-panel-icon-wrapper icon-message"> <svg-icon icon-class="message" class-name="card-panel-icon" /> </div> <div class="card-panel-description"> <div class="card-panel-text"> Messages </div> <count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" /> </div> </div> </el-col> <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="card-panel" @click="handleSetLineChartData('start')"> <div class="card-panel-icon-wrapper icon-money"> <svg-icon icon-class="star" class-name="card-panel-icon" /> </div> <div class="card-panel-description"> <div class="card-panel-text"> Purchases </div> <count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" /> </div> </div> </el-col> <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="card-panel" @click="handleSetLineChartData('zip')"> <div class="card-panel-icon-wrapper icon-money"> <svg-icon icon-class="zip" class-name="card-panel-icon" /> </div> <div class="card-panel-description"> <div class="card-panel-text"> Purchases </div> <count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" /> </div> </div> </el-col> </el-row> </template> <script> import CountTo from 'vue-count-to' export default { components: { CountTo }, methods: { handleSetLineChartData(type) { this.$emit('handleSetLineChartData', type) } } } </script> <style lang="scss" scoped> .panel-group { margin-top: 18px; .card-panel-col { margin-bottom: 32px; } .card-panel { height: 108px; cursor: pointer; font-size: 12px; position: relative; overflow: hidden; color: #666; background: #fff; box-shadow: 4px 4px 40px rgba(0, 0, 0, .05); border-color: rgba(0, 0, 0, .05); &:hover { .card-panel-icon-wrapper { color: #fff; } .icon-people { background: #40c9c6; } .icon-message { background: #36a3f7; } .icon-money { background: #f4516c; } .icon-shopping { background: #34bfa3 } } .icon-people { color: #40c9c6; } .icon-message { color: #36a3f7; } .icon-money { color: #f4516c; } .icon-shopping { color: #34bfa3 } .card-panel-icon-wrapper { float: left; margin: 14px 0 0 14px; padding: 16px; transition: all 0.38s ease-out; border-radius: 6px; } .card-panel-icon { float: left; font-size: 48px; } .card-panel-description { float: right; font-weight: bold; margin: 26px; margin-left: 0px; .card-panel-text { line-height: 18px; color: rgba(0, 0, 0, 0.45); font-size: 16px; margin-bottom: 12px; } .card-panel-num { font-size: 20px; } } } } @media (max-width:550px) { .card-panel-description { display: none; } .card-panel-icon-wrapper { float: none !important; width: 100%; height: 100%; margin: 0 !important; .svg-icon { display: block; margin: 14px auto !important; float: none !important; } } } </style>
折线图饼图联动组件
<template> <div id="centerid" :class="className" :style="{height:height,width:width}"/> </template> <script>import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize' export default { mixins: [resize], props: { className: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '400px' }, autoResize: { type: Boolean, default: true }, chartData: { type: Object, required: true } }, data() { return { chart: null } }, watch: { chartData: { deep: true, handler(val) { this.setOptions(val) } } }, mounted() { this.$nextTick(() => { this.initChart() }) }, beforeDestroy() { if (!this.chart) { return } this.chart.dispose() this.chart = null }, methods: { initChart() { debugger this.chart = echarts.init(this.$el, 'macarons') this.setOptions(this.chartData) this.chart.on('updateAxisPointer', event => { let xAxisInfo = event.axesInfo[0]; if (xAxisInfo) { let dimension = xAxisInfo.value + 1; this.chart.setOption({ series: { id: 'pie', label: { formatter: '{b}: {@[' + dimension + ']} ({d}%)' }, encode: { value: dimension, tooltip: dimension } } }); } }) }, setOptions({newVisitis} = {}) { this.chart.setOption({ legend: {}, title: { text: newVisitis.title }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' }, padding: [5, 10] }, dataset: { source: newVisitis.source }, xAxis: { type: 'category', boundaryGap: false, axisTick: { show: false }}, yAxis: { gridIndex: 0, axisTick: { show: false }}, grid: { width: '40%', height: '60%', left: '5%', bottom: 20, top: 30, containLabel: true}, series: [ { type: 'line', smooth: true, seriesLayoutBy: 'row', animationDuration: 2800, animationEasing: 'cubicInOut' }, { type: 'line', smooth: true, seriesLayoutBy: 'row', animationDuration: 2800, animationEasing: 'cubicInOut' }, { type: 'line', smooth: true, seriesLayoutBy: 'row', animationDuration: 2800, animationEasing: 'cubicInOut' }, { type: 'line', smooth: true, seriesLayoutBy: 'row', animationDuration: 2800, animationEasing: 'cubicInOut' }, { type: 'pie', id: 'pie', radius: '30%', center: ['70%', '45%'], height: '70%', left: '50%', label: { formatter: '{b}: {@2012} ({d}%)' }, encode: { itemName: 'product', value: '2012', tooltip: '2012' } } ] }) }, }, } </script>
调用饼图并组装数据
<template> <div class="dashboard-editor-container"> <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> <panel-group @handleSetLineChartData="handleSetLineChartData" /> </el-row> <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> <line-pie-chart :chart-data="linePieChartData"></line-pie-chart> </el-row> <el-row :gutter="32"> <el-col :xs="24" :sm="24" :lg="8"> <div class="chart-wrapper"> <raddar-chart /> </div> </el-col> <el-col :xs="24" :sm="24" :lg="8"> <div class="chart-wrapper"> <pie-chart /> </div> </el-col> <el-col :xs="24" :sm="24" :lg="8"> <div class="chart-wrapper"> <bar-chart /> </div> </el-col> </el-row> </div> </template> <script> import LineChart from './components/LineChart' import RaddarChart from './components/RaddarChart' import PieChart from './components/PieChart' import BarChart from './components/BarChart' import LinePieChart from './components/LinePieChart' import PanelGroup from './components/PanelGroup' const lineChartData = { newVisitis: { expectedData: [100, 120, 161, 134, 105, 160, 165], actualData: [120, 82, 91, 154, 162, 140, 145] } } const linePieChartData = { newVisitis:{ newVisitis: { title:'newVisitis', source: [ ['product', '2012', '2013', '2014', '2015', '2016', '2017'], ['成功', 4, 3, 6, 5, 8, 9], ['失败', 86, 92, 85, 83, 73, 55], ['拉了', 24, 67, 79, 86, 65, 82], ['失联', 15, 27, 29, 12, 23, 19] ] } }, messages:{ newVisitis: { title:'messages', source: [ ['product', '2012', '2013', '2014', '2015', '2016', '2017'], ['成功', 41, 30, 65, 53, 83, 98], ['失败', 8, 9, 5, 8, 3, 5], ['拉了', 14, 17, 7, 16, 15, 12], ['失联', 55, 67, 69, 72, 53, 39] ] } }, start:{ newVisitis: { title:'start', source: [ ['product', '2012', '2013', '2014', '2015', '2016', '2017'], ['成功', 41, 30, 65, 53, 83, 98], ['失败', 86, 92, 85, 83, 73, 55], ['拉了', 4, 7, 9, 6, 5, 2], ['失联', 15, 17, 19, 12, 13, 19] ] } }, zip:{ newVisitis: { title:'start', source: [ ['product', '2012', '2013', '2014', '2015', '2016', '2017'], ['成功', 4, 3, 6, 5, 8, 9], ['失败', 26, 12, 25, 33, 23, 15], ['拉了', 44, 47, 49, 46, 45, 42], ['失联', 15, 17, 19, 12, 13, 19] ] } }, } export default { name: 'DashboardAdmin', components: { LineChart, RaddarChart, PieChart, BarChart, LinePieChart, PanelGroup }, data() { return { lineChartData: lineChartData.newVisitis, linePieChartData: linePieChartData.newVisitis } }, methods: { handleSetLineChartData(type) { this.linePieChartData = linePieChartData[type] } } } </script> <style lang="scss" scoped> .dashboard-editor-container { padding: 32px; background-color: rgb(240, 242, 245); .github-corner { position: absolute; top: 0px; border: 0; right: 0; } .chart-wrapper { background: #fff; padding: 16px 16px 0; margin-bottom: 32px; } } @media (max-width:1024px) { .chart-wrapper { padding: 8px; } } </style>
本文来自博客园,作者:l-coil,转载请注明原文链接:https://www.cnblogs.com/l-coil/p/12782093.html