vue中简单封装antV G2图表

之前记过vue中antV G2图表的使用https://www.jianshu.com/p/a836ae8aeeb7(折线)

现在为了减少代码量,简单封装一下,效果如下

image-20200909132848799.png

基本使用

子组件

新建LineChart.vue文件,里面是要封装的内容。

<!-- LineChart.vue 多折线-->
    
<template>
    <div>
        <div style="padding: 30px;height: 40vh;" :id="id"></div>    //id设成属性值方便多次使用,样式
    </div>
</template>



<script>
import { Chart } from "@antv/g2";   // 引入G2 Chart对象

export default {
    name: 'LineChart',              // 组件名
    props: {                        // 用到的属性,在父组件里用v-modal绑定
        chartData: {                // 图表要使用的数据,在父组件里处理过、符合格式的数组
            type: Array,
            default: () => [],
        },
        id: {                       // 图表容器id
            type: String,
            default: '',
        }
    },
    watch: {                        // watch 监听chartData,发生变化的时候更新图表,初始化和更新数据的时候都适用
        chartData() {                        
            console.log('watch!!!!');
            this.initLineChart();
        }
    },
    data() {
        return {
            chart: null,            // 为了保证更新图表的时候不会重复创建Chart对象,先声明一下,方便之后判断
        };
    },
    mounted() {
        // this.initLineChart();    // mounted中调用方法不适合异步请求数据,initLineChart的时候,this.chartData是空的
    },
    methods: {
        initLineChart() {
            this.chart && this.chart.destroy();     // 上面说过的,如果图表对象存在就先删除,不然会重复创建,会显示两个图表
            console.log('initLineChart success!!');
            
            this.chart = new Chart({
                container: this.id,                 // 用id属性
                autoFit: true,
                // height: 500
            });

            this.chart.data(this.chartData);        // 图表数据
            this.chart.scale({
                time: {
                    range: [0, 1]
                },
                count: {
                    min: 0,
                    nice: true
                },
            });
            this.chart.tooltip({
                showCrosshairs: true, // 展示 Tooltip 辅助线
                shared: true,
            });
            this.chart.axis('count', {
                 label: {
                     formatter: function formatter(val) {
                         return val ;
                     }
                 }
            });           
            this.chart.line().position('time*count').color('type').shape('smooth');
            this.chart.point().position('time*count').color('type').size(4).shape('circle').style({
                stroke: '#fff',
                lineWidth: 1
            });
            this.chart.render();
        },
    }
}
</script>

<style lang="less" scoped></style>

父组件引用子组件

<template>
    <div>
        <LineChart :chartData="chartdata" :id="'chartDiv'" />   //这里:id绑定格式要绑字符串
    </div>
</template>

<script>
import LineChart from '@/components'                            // 引入自定义的组件名,路径按自己的情况
// import { LineChart } from '@/components'                     // components的index.js统一export之后的引用方法
const DataSet = require('@antv/data-set');                      // abtv处理数据的

export default {
  components: {
    LineChart,              // 引用后需要注册组件
  },
  data() {
    return {
      chartdata:[],
      originData: [         // 实际从接口获取,暂先用假的
          { time: "周一", 激活设备数: 1234, 在线用户数: 124, 生理指标数:2352, 消息数:283 },
          { time: "周二", 激活设备数: 1245, 在线用户数: 364, 生理指标数:1534, 消息数:234 },
          { time: "周三", 激活设备数: 1456, 在线用户数: 428, 生理指标数:1926, 消息数:992 },
          { time: "周四", 激活设备数: 1526, 在线用户数: 523, 生理指标数:2538, 消息数:720 },
          { time: "周五", 激活设备数: 1548, 在线用户数: 92, 生理指标数:945, 消息数:1347 },
          { time: "周六", 激活设备数: 1798, 在线用户数: 242, 生理指标数:2523, 消息数:124 },
          { time: "周日", 激活设备数: 1723, 在线用户数: 131, 生理指标数:1583, 消息数:732 },
      ]
    };
  },
  mounted() {
    this.initData();                // 调用获取数据的方法
      // console.log('chartdata =>',this.chartdata)
      // console.log('ref.chartData =>',this.$refs.chart.chartData)
  },
  methods: {
    initData() {                    // 得到数据,对数据格式进行一些处理,上篇说过。
      let ds = new DataSet();       // 上篇是双曲线,一条转成两条,现在就是一条转换成四条,方法都一样。
      let dv = ds.createView().source(this.originData);
      // fold 方式完成了行列转换,如果不想使用 DataSet 直接手工转换数据即可
      dv.transform({
          type: 'fold',
          fields: ['激活设备数','在线用户数','生理指标数','消息数'],  // 展开字段集
          key: 'type',                                          // key字段
          value: 'count'                                        // value字段 这个字段和time字段和子组件里的字段是要对应的。
      });
      this.chartdata = dv.rows;     // 处理过后的数据赋值给this.chartdata
      console.log('initData!!!')
    },
  },
}
</script>

<style lang="less" scoped>
</style>

★需求是Tabs页展示不同时段的数据统计结果

(明明用按钮更方便☺,用按钮的话只要一个图表,更新数据就可以了。更新数据相关https://blog.csdn.net/weixin_42275932/article/details/90080199?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight

UI组件用的是antdv,将四个图表挂在四个tab-pane上,需要注意的是所有tab-pane页都要强行渲染,api用forceRender(被隐藏时是否渲染)

<div class="dataStastic">
    <a-tabs 
        defaultActiveKey="1"
        size="large"
        :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}"
    >
        <a-tab-pane key="1" tab="小时">
            <LineChart :chartData="chartdataHour" :id="'chartDiv1'" />
        </a-tab-pane>
        <a-tab-pane key="2" tab="天" forceRender>
            <LineChart :chartData="chartdataDay" :id="'chartDiv2'" />
        </a-tab-pane>
        <a-tab-pane key="3" tab="周" forceRender>
            <LineChart :chartData="chartdataWeek" :id="'chartDiv3'" />
        </a-tab-pane>
        <a-tab-pane key="4" tab="月" forceRender>
            <LineChart :chartData="chartdataMonth" :id="'chartDiv4'" />
        </a-tab-pane>
    </a-tabs>
</div>

不渲染的话是空白的!!!不渲染的话是空白的!!!不渲染的话是空白的!!!


优化

目前是横坐标的字段是time,纵坐标的字段是count,默认有坐标轴,辅助线,和图例。

控制一下坐标轴辅助线和图例的显示,将高度也放在父组件里传入。

LineChart.vue的prop:

props: {
        chartData: {
            type: Array,
            default: () => [],
        },
        id: {
            type: String,
            default: '',
        },
        height: {           //高度
            type: Number,
            default: 300,
        },
        legend: {           //图例
            type: Boolean,
            default:true,
        },
        axisX: {            //横坐标
            type: Boolean,
            default:true,
        },
        axisY: {            //纵坐标
            type: Boolean,
            default:true,
        },
    },

LineChart.vue的initLineChart:

initLineChart() {
    this.chart && this.chart.destroy();     //如果存在就先删除
    console.log('initLineChart success!!');
    console.log(this.chartData)
    this.chart = new Chart({
        container: this.id,
        autoFit: true,
        height: this.height,                // 控制高度
    });

    this.chart.data(this.chartData);
    this.chart.scale({
        time: {
            range: [0, 1]
        },
        count: {
            min: 0,
            nice: true
        },
    });
    this.chart.tooltip({
        showCrosshairs: true, // 展示 Tooltip 辅助线
        shared: true,
    });
    this.chart.axis('count',this.axisY);    //控制横纵坐标,图例
    this.chart.axis('time',this.axisX);
    this.chart.legend(this.legend);
    
    this.chart.line().position('time*count').color('type').shape('smooth');
    this.chart.point().position('time*count').color('type').size(4).shape('circle').style({
        stroke: '#fff',
        lineWidth: 1
    });
    this.chart.render();
},

父组件的template:

<LineChart :chartData="chartdata" :id="'chartDiv'" :height="100" :legend="false" :axisX="false" :axisY="false"/>

这样就是高度100,不显示图例,也不显示横坐标、纵坐标。

其他想要控制的也可以这样。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。