【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件

一些废话

	默默做前端,分享一些自己在项目需求实现中遇到的奇妙问题
	(主要是网上搜索不到解决办法自己解决后的总结方法和解决办法但不全面,自己整理总结的存档)。

事发背景

	原型绘制了需要同时展示多个指标的数据气泡图,想到可以使用antv的气泡图
	刚好契合,但是官方文档写的未免过于简洁,遂记录之。

【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件_第1张图片
想原型表达的实现效果如图(码掉的是气泡标出的值标签显示mainlabel和坐标轴参数,鼠标滑入气泡展示五个业务指标)。
于是lz在antv文档找到下图的示例们(附链接:气泡图 - AntV (antfin.com))。
图一
【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件_第2张图片
图二
【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件_第3张图片
让它们混合在一起~真滴是非常完美,很相近,遂将代码扒之放入俺滴PopChart.vue文件。

实现效果

初始完成效果:

【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件_第4张图片

调整后完成效果:

【VUE3+AntV-G2】数据可视化 封装antv G2 气泡图组件_第5张图片

实现效果所使用的数据都是自己瞎编的,然后还未进行接口联调,所呈现的样式和效果都是默认滴,后续大家根据自己的想法或者项目需求慢慢调整即可。

安装和引入

首先要在项目文件安装antv G2

1.通过 npm 安装

npm install @antv/g2 --save

成功安装完成之后,即可使用 importrequire 进行引用。

import { Chart } from '@antv/g2';

2.浏览器引入

既可以通过将脚本下载到本地也可以直接引入在线资源:

<!-- 引入在线资源,选择你需要的 g2 版本以替换 version 变量 -->
<script src="https://gw.alipayobjects.com/os/lib/antv/g2/{{version}}/dist/g2.min.js"></script>
<!-- 引入本地脚本 -->
<script src="./g2.js"></script>

使用 script 标签引入 G2 资源时,挂载在 window 上的变量名为 G2,所以在上述实例中需要加上 G2 的前缀。如下:

const chart = new G2.Chart({
  /* your options */
})

实现思路

  1. 分析图表构成。框架是不显示横纵轴的轴线和刻度线,但是显示刻度数值,并且辅助线垂直相交于(1,1)点(后期如果是两轴数据的中位数也可以使用变量进行数据替换),图例、网格线原型没要求,之后样式再细调,所以我们轴样式使用图二,气泡样式使用图一。

  2. pop-chart容器

在template内创建div图表容器

然后在state里定义图表对象和图表中显示的数据

const state = reactive({
  chart:null,//图表对象
  showData:[
    {
      "统计时间": '2022-01',
      "指标系数x": 1.08,
      "指标系数y": 1.09,
      "气泡大小展示的指标": 21,
      "气泡主标签指标": "ICU",
    },
  ]//图表中将要显示的数据
})

创建chart

const popChart = (data) => {
  state.chart = new Chart({
    container: 'popChart',//chart容器id
    autoFit: true,//图表是否自适应容器宽高,默认为 false
    padding: [60, 60, 60, 60],//图表内边距,依次为:上,右,下,左
    // defaultInteractions:"ellipsis-text",//配置图表默认交互,仅支持字符串形式。G2 默认支持的交互有 'tooltip', 'legend-filter', 'legend-active', 'continuous-filter', 'ellipsis-text'
    pixelRatio: window.devicePixelRatio,//设置设备像素比,默认取浏览器的值 window.devicePixelRatio
    renderer: "canvas",//指定渲染引擎,默认使用 canvas。可选:'canvas' | 'svg'
    theme: "",//配置主题,目前 g2 默认有 dark 主题模式,如需要自定义配置,可以先通过 registerTheme 注册主题,再设置主题 key。
    visible: true,//chart 是否可见,默认为 true,设置为 false 则会隐藏。
  });
}
  1. 坐标系设置

定义咱的x、y指标系数

const popChartAxis = () => {
  var scale = {};
  scale["指标系数x"] = {
      type: 'pow',
      nice: true,
  }
  scale["指标系数y"] = {
      type: 'pow',
      nice: true,
  }
  state.chart.scale(scale, {//Y轴 字段是 度量
      nice: false,//是否自动调整 min、max 。默认为false
      min: 0.8,//度量最小值,
      max: 2,//度量最大值,如果不需要指定最大值可以设置max=null,或者不要填该参数
  });

下面是x、y轴方法,x、y轴线和刻度线不显示,我这里设为白色了

//设置Y轴
  //state.chart.axis("指标系数y",false);//不需要Y轴,可以设置false
  state.chart.axis("指标系数y", {//Y轴样式
    grid: {
      line: {
        type: "line",
        style: {
          // fill:'#fff',
          stroke: "#ccc",//网格线颜色
          opacity: 1,//网格线透明度
          lineDash: [1,3],//虚线
        }
      },
    },
    label: {
      style: {
        fill:"#000",///Y轴文字颜色
        fontFamily: "Microsoft YaHei",///Y轴文字字体
        fontWeight: 400,///Y轴文字粗细
        fontsize: 12,///Y轴文字大小
      }
    },
    line: {
      style: {
        stroke:"#fff",//坐标轴颜色
      }
    },
    tickLine: {
      style: {
        stroke:"#fff",//刻度线颜色
      }
    },
    subTickLine: {
      style: {
        stroke:"#fff",//小刻度颜色
      }
    }
  });
//设置X轴
  // state.chart.axis("指标系数x",false);//不需要轴,可以设置false
  state.chart.axis("指标系数x", {//X轴样式
    label: {
      formatter: (val) => {
        return val;
        // return +val * 100 + '%';
      },
      style: {
        fill:"#000",//文字颜色
        fontFamily: "Microsoft YaHei",//文字字体
        fontWeight: 400,//文字粗细
        fontsize: 12,//文字大小
      }
    },
    line: {
      style: {
        stroke:"#fff",//坐标轴颜色
      }
    },
    tickLine: {
      style: {
        stroke:"#fff",//刻度线颜色
      }
    },
    subTickLine: {
      style: {
        stroke:"#fff",//小刻度颜色
      }
    }
  });

然后是辅助线设置

  state.chart.guide().line({ //y辅助线
    top: true,
    start: [1, 'min'], //star\end 数字表示轴向原点偏移
    end: [1, 'max'],
    text: {
      content: '', //辅助线轴标签
      position: 'end',
      autoRotate: false,
      style: {
        textAlign: 'start' //标签显示位置
      }
    }
  });
  state.chart.guide().line({ //x辅助线
    top: true,
    start: ['min', 1],
    end: ['max', 1],
    text: {
      content: '',
      position: 'end',
      style: {
        textAlign: 'end'
      }
    }
  })
}
  1. 设置PopChart数据
const popChartData = () =>{
  state.chart.data(state.showData);
}
  1. 设置图表气泡相关属性【气泡样式】
const popChartStyle = () => {
  var line = state.chart.point();
  line.size(6)//圆点大小
  .style({ 
    // strokeOpacity:1,
    // fill: attrs.style.pointColor,
    stroke:"#000",//圆点边框颜色
    
  })
  .state({
    // selected: {
    //   style: {
    //     stroke:'red',
    //   }
    // }
    active: {
      style: {
      stroke:"#2681ff",//鼠标经过 边框颜色
      }
    }
  })
  .position("指标系数x"+"*"+"指标系数y")//X轴 * Y轴
  .size("气泡大小展示的指标"+"",[1,40])//气泡半径范围 1-30
  .color("气泡主标签指标", ["rgba(211, 202, 139, 0.3)", "rgba(211, 229, 252, 0.3)", "rgba(63, 110, 78, 0.3)", "rgba(164, 192, 77, 0.3)", "rgba(110, 152, 146, 0.3)"])//参数1:气泡主标签指标字段为分组字段,参数2:颜色数组,散点的颜色会循环的从颜色数组中取出来,这里我采用的都是带透明度的颜色
  .tooltip("指标系数x"+"*"+"指标系数y"+"*"+"气泡大小展示的指标"+"*"+"气泡主标签指标")
  .shape('circle');
  //柱子上是否显示值标签
  //line.label(false);//入组病例数
  line.label("气泡主标签指标", {//标签值
    content: (originData) => {
      return originData["气泡主标签指标"];//设置值标签最终显示的内容
    },
    style: {
      fill: "#000",
      fontFamily: "Microsoft YaHei",
      fontWeight: 400,
      fontsize: 16,
      // fill: "#000000",
    },
    position:"top",//显示位置
  })
}
  1. 设置鼠标移入气泡提示框信息样式
const popChartTooltip = () => {
  state.chart.tooltip({
    showMarkers: false,
    showCrosshairs: false,
    domStyles: {
      'g2-tooltip': {
        background:"rgba(00, 00, 00,0.5)",//背景RGBA形式的值
        color:"#fff",//文字颜色
        boxShadow:"0px 0px 5px #fff",//阴影大小 阴影颜色 
      },
    },
    customItems: (items) => {//自定义显示的内容格式
      // console.log("items")
      // console.log(items)
      // items[0].name="xx";
      return items;
    },
  });
}

7.其他整理的点(图例、动画、点击事件)

//设置图例
const popChartLegend = () => {
  // state.chart.legend(false);//设置为false,表示不显示图例
  state.chart.legend("气泡主标签指标", {
    position: "bottom",//图例位置:"top" | "top-left" | "top-right" | "right" | "right-top" | "right-bottom" | "left" | "left-top" | "left-bottom" | "bottom" | "bottom-left" | "bottom-right"
    itemName: {
      style: {
        fill: "#000",
        fontFamily: "Microsoft YaHei",
        fontWeight: 400,
        fontsize: 16,
      }
    },
    pageNavigator: {
      marker: {//分页器指示箭头配置项
        style: {
          // 非激活,不可点击态时的填充色设置
          inactiveFill: "#000",//分页器:箭头颜色
          inactiveOpacity: 1,//分页器:箭头透明度
          // 默认填充色设置
          fill: "#000",//分页器:颜色
          opacity: 1,//分页器:透明度
          size: 12,//分页器:大小
        },
      },
      text: {//分页器指示文本配置项
        style: {
          fill: "#000",//分页器:文本颜色
          fontsize: 12,//分页器:文本大小
        },
      },
    },
  });
}
//设置动画
const popChartAnimate = () => {
  // state.chart.animate(false);//设置为false,表示不使用动画效果
  state.chart.animate({
    // 初始化时的入场动画
    appear: {
      animation: 'fade-in', // 动画名称:'fade-in'|'fan-in'|'scale-inx'|'scale-iny'|'path-in'|'zoom-in'|'clip-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的出现动画
    enter: {
      animation: 'fade-in', //动画名称:'fade-in'|'fan-in'|'scale-inx'|'scale-iny'|'path-in'|'zoom-in'|'clip-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的动画
    leave: {
      animation: 'path-out', //动画名称:'fade-out'|'path-out'|'zoom-out'|'lineWidth-out'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的变化动画
    update: {
      animation: 'fade-in', //动画名称:'fade-in'|'fan-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
  })
}
//添加点击事件
const popChartClickEvent = () => {
  state.chart.on('element:click', (ev) => {
    var data = ev.data.data;
    console.log(data);
    alert(JSON.stringify(data)); //点击事件:单击弹出提示框显示单个气泡的数组数据
  });
}

8.渲染图表

state.chart.render();

总结和完整代码

<template>
  <div id='popChart' style="width:100%;height:366px"></div>
</template>

<script setup>
import { reactive,getCurrentInstance, onMounted } from 'vue';
import { Chart } from '@antv/g2';

const state = reactive({
  chart:null,//图表对象
  showData:[
    {
      "统计时间": '2022-01',
      "指标系数x": 1.08,
      "指标系数y": 1.09,
      "气泡大小展示的指标": 21,
      "气泡主标签指标": "ICU",
    },
  ]//图表中将要显示的数据
})
// 创建chart
const popChart = (data) => {
  state.chart = new Chart({
    container: 'popChart',//chart容器id
    autoFit: true,//图表是否自适应容器宽高,默认为 false
    padding: [60, 60, 60, 60],//图表内边距,依次为:上,右,下,左
    // defaultInteractions:"ellipsis-text",//配置图表默认交互,仅支持字符串形式。G2 默认支持的交互有 'tooltip', 'legend-filter', 'legend-active', 'continuous-filter', 'ellipsis-text'
    pixelRatio: window.devicePixelRatio,//设置设备像素比,默认取浏览器的值 window.devicePixelRatio
    renderer: "canvas",//指定渲染引擎,默认使用 canvas。可选:'canvas' | 'svg'
    theme: "",//配置主题,目前 g2 默认有 dark 主题模式,如需要自定义配置,可以先通过 registerTheme 注册主题,再设置主题 key。
    visible: true,//chart 是否可见,默认为 true,设置为 false 则会隐藏。
  });
}
//设置轴
const popChartAxis = () => {
  var scale = {};
  scale["指标系数x"] = {
      type: 'pow',
      nice: true,
  }
  scale["指标系数y"] = {
      type: 'pow',
      nice: true,
  }
  state.chart.scale(scale, {//Y轴 字段是 度量
      nice: false,//是否自动调整 min、max 。默认为false
      min: 0.8,//度量最小值,
      max: 2,//度量最大值,如果不需要指定最大值可以设置max=null,或者不要填该参数
  });
  //设置Y轴
  //state.chart.axis("指标系数y",false);//不需要Y轴,可以设置false
  state.chart.axis("指标系数y", {//Y轴样式
    grid: {
      line: {
        type: "line",
        style: {
          // fill:'#fff',
          stroke: "#ccc",//网格线颜色
          opacity: 1,//网格线透明度
          lineDash: [1,3],//虚线
        }
      },
    },
    label: {
      style: {
        fill:"#000",///Y轴文字颜色
        fontFamily: "Microsoft YaHei",///Y轴文字字体
        fontWeight: 400,///Y轴文字粗细
        fontsize: 12,///Y轴文字大小
      }
    },
    line: {
      style: {
        stroke:"#fff",//坐标轴颜色
      }
    },
    tickLine: {
      style: {
        stroke:"#fff",//刻度线颜色
      }
    },
    subTickLine: {
      style: {
        stroke:"#fff",//小刻度颜色
      }
    }
  });
  //设置X轴
  // state.chart.axis("指标系数x",false);//不需要轴,可以设置false
  state.chart.axis("指标系数x", {//X轴样式
    label: {
      formatter: (val) => {
        return val;
        // return +val * 100 + '%';
      },
      style: {
        fill:"#000",//文字颜色
        fontFamily: "Microsoft YaHei",//文字字体
        fontWeight: 400,//文字粗细
        fontsize: 12,//文字大小
      }
    },
    line: {
      style: {
        stroke:"#fff",//坐标轴颜色
      }
    },
    tickLine: {
      style: {
        stroke:"#fff",//刻度线颜色
      }
    },
    subTickLine: {
      style: {
        stroke:"#fff",//小刻度颜色
      }
    }
  });
  state.chart.guide().line({ //y辅助线
    top: true,
    start: [1, 'min'], //star\end 数字表示轴向原点偏移
    end: [1, 'max'],
    text: {
      content: '', //辅助线轴标签
      position: 'end',
      autoRotate: false,
      style: {
        textAlign: 'start' //标签显示位置
      }
    }
  });
  state.chart.guide().line({ //x辅助线
    top: true,
    start: ['min', 1],
    end: ['max', 1],
    text: {
      content: '',
      position: 'end',
      style: {
        textAlign: 'end'
      }
    }
  })
}
//设置chart数据
const popChartData = () =>{
  state.chart.data(state.showData);
}
//设置气泡样式
const popChartStyle = () => {
  var line = state.chart.point();
  line.size(6)//圆点大小
  .style({ 
    // strokeOpacity:1,
    // fill: attrs.style.pointColor,
    stroke:"#000",//圆点边框颜色
    
  })
  .state({
    // selected: {
    //   style: {
    //     stroke:'red',
    //   }
    // }
    active: {
      style: {
      stroke:"#2681ff",//鼠标经过 边框颜色
      }
    }
  })
  .position("指标系数x"+"*"+"指标系数y")//X轴 * Y轴
  .size("气泡大小展示的指标"+"",[1,40])//气泡半径范围 1-30
  .color("气泡主标签指标", ["rgba(211, 202, 139, 0.3)", "rgba(211, 229, 252, 0.3)", "rgba(63, 110, 78, 0.3)", "rgba(164, 192, 77, 0.3)", "rgba(110, 152, 146, 0.3)"])//参数1:气泡主标签指标字段为分组字段,参数2:颜色数组,散点的颜色会循环的从颜色数组中取出来,这里我采用的都是带透明度的颜色
  .tooltip("指标系数x"+"*"+"指标系数y"+"*"+"气泡大小展示的指标"+"*"+"气泡主标签指标")
  .shape('circle');
  //柱子上是否显示值标签
  //line.label(false);//入组病例数
  line.label("气泡主标签指标", {//标签值
    content: (originData) => {
      return originData["气泡主标签指标"];//设置值标签最终显示的内容
    },
    style: {
      fill: "#000",
      fontFamily: "Microsoft YaHei",
      fontWeight: 400,
      fontsize: 16,
      // fill: "#000000",
    },
    position:"top",//显示位置
  })
}
//提示框样式
const popChartTooltip = () => {
  state.chart.tooltip({
    showMarkers: false,
    showCrosshairs: false,
    domStyles: {
      'g2-tooltip': {
        background:"rgba(00, 00, 00,0.5)",//背景RGBA形式的值
        color:"#fff",//文字颜色
        boxShadow:"0px 0px 5px #fff",//阴影大小 阴影颜色 
      },
    },
    customItems: (items) => {//自定义显示的内容格式
      // console.log("items")
      // console.log(items)
      // items[0].name="xx";
      return items;
    },
  });
}
//设置图例
const popChartLegend = () => {
  // state.chart.legend(false);//设置为false,表示不显示图例
  state.chart.legend("气泡主标签指标", {
    position: "bottom",//图例位置:"top" | "top-left" | "top-right" | "right" | "right-top" | "right-bottom" | "left" | "left-top" | "left-bottom" | "bottom" | "bottom-left" | "bottom-right"
    itemName: {
      style: {
        fill: "#000",
        fontFamily: "Microsoft YaHei",
        fontWeight: 400,
        fontsize: 16,
      }
    },
    pageNavigator: {
      marker: {//分页器指示箭头配置项
        style: {
          // 非激活,不可点击态时的填充色设置
          inactiveFill: "#000",//分页器:箭头颜色
          inactiveOpacity: 1,//分页器:箭头透明度
          // 默认填充色设置
          fill: "#000",//分页器:颜色
          opacity: 1,//分页器:透明度
          size: 12,//分页器:大小
        },
      },
      text: {//分页器指示文本配置项
        style: {
          fill: "#000",//分页器:文本颜色
          fontsize: 12,//分页器:文本大小
        },
      },
    },
  });
}
//设置动画
const popChartAnimate = () => {
  // state.chart.animate(false);//设置为false,表示不使用动画效果
  state.chart.animate({
    // 初始化时的入场动画
    appear: {
      animation: 'fade-in', // 动画名称:'fade-in'|'fan-in'|'scale-inx'|'scale-iny'|'path-in'|'zoom-in'|'clip-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的出现动画
    enter: {
      animation: 'fade-in', //动画名称:'fade-in'|'fan-in'|'scale-inx'|'scale-iny'|'path-in'|'zoom-in'|'clip-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的动画
    leave: {
      animation: 'path-out', //动画名称:'fade-out'|'path-out'|'zoom-out'|'lineWidth-out'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
    // 更新时的变化动画
    update: {
      animation: 'fade-in', //动画名称:'fade-in'|'fan-in'
      easing: 'easeQuadIn', // 动画缓动效果
      delay: 100, // 动画延迟执行时间
      duration: 600 // 动画执行时间
    },
  })
}
//添加点击事件
const popChartClickEvent = () => {
  state.chart.on('element:click', (ev) => {
    var data = ev.data.data;
    console.log(data);
    alert(JSON.stringify(data)); //点击事件:单击弹出提示框显示单个气泡的数组数据
  });
}
//初始化图表方法
const init = () => {
  popChart();//创建chart
  popChartData();//设置字段和数据
  popChartAxis();//设置坐标轴和度量
  popChartTooltip();//设置提示信息
  state.chart.interaction('element-active');//设置图表样式
  popChartStyle();//设置图表气泡相关属性
  // chart.legend(false);//设置为false,表示不显示图例
  popChartLegend();//设置图例
  popChartAnimate();//设置动画
  //渲染图表
  state.chart.render();
  //添加点击事件
  popChartClickEvent();
}
defineExpose({ // 向父组件暴露调用方法
})
onMounted(() => { //挂载初始化方法
  init()
})
</script>

参考资料

1.快速上手 (yuque.com)
2.带文本的气泡图 - AntV (antfin.com)

你可能感兴趣的:(ANTV,信息可视化,vue.js,前端,javascript)