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,不显示图例,也不显示横坐标、纵坐标。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343