之前记过vue中antV G2图表的使用https://www.jianshu.com/p/a836ae8aeeb7(折线)
现在为了减少代码量,简单封装一下,效果如下
基本使用
子组件
新建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,不显示图例,也不显示横坐标、纵坐标。
其他想要控制的也可以这样。