参与图表组件库开发(要求使用Echarts或G2)

因为这两个都没用过,翻阅多篇文章,最终选择入坑G2,要用就用新技术!所以特此记录一些常用的,方便以后避坑。Echarts或G2对于我这样没用过的人来说API实在太多了没法记,所以我也不喜欢一点一点去看官方文档,更多是了解了基础原理直接看官网例子代码,不知道有人和我一样么?所以常用的我都会在下面代码注释中体现到底是干什么的。不会将某个属性展开说,什么包含那些等,遇到问题知道去找那个属性关键词就可以了

G2核心概念视觉通道

在 G2 中我们实现了如下类型的视觉通道(也称图形属性):、

  • position(位置),二维坐标系内可以映射到 x,y,三维坐标系可以映射到 x,y,z。
  • color(颜色),包含了色调、饱和度和亮度。
  • size(大小),不同的图形对大小的定义有所差异。
  • shape(形状),图形的形状决定了某个图表类型的表现方式。例如 点图,可以使用圆点、三角形、小 的图片表示;线图可以使用折线、曲线、点线等表现形式。
G2 图表组成

1.G2在react中的写法,看了各种写法,个人更加偏爱这种:

//写在useEffect当中我是觉得方便一些,但是有缺陷就是在外面找不到chart实例,没法对chart做操作
//所以有知道的大佬可以说一下一般标准的写法是怎么写的
useEffect(() => {const chart = new Chart({container: container,autoFit: true,height: 500,});...chart.interval().position('type*value')...chart.render();},[ ])

2.示例图加注释:

a.圆形柱状图?(颜色随数据改变)

我做的:

要求的:

//图片中渐变边框我选择用css实现,G2应该也可以实现但是很麻烦
//可以理解为两个极坐标的柱状图,一深一浅重叠
const used=68;   //使用率 假数据
let colors=['#D3EAFF', '#2495FF'];   //颜色假数据
const data1: object[] = [];       //深色假数据for (let i = 0; i < 20; i++) {       //控制柱状个数data1.push({type: i + '',value: 10,});}let data2: object[]= [];  //浅色假数据for (let i = 0; i < 20; i++) {const item = { type: '', value: 1 };item.type = i + '';item.value = 10;let transused = used / 5;  //100为满,20个柱子所以/5 转换if (i >= transused) {item.value = 0;}data2.push(item);}const chart = new Chart({      //创建Chart实例container: container,      //容器id名称autoFit: true,      //是否随着屏幕自适应宽高height: 500,        //也可以单独设置宽高});chart.legend(false); //不显示图例chart.tooltip(false); //不显示提示  就是鼠标滑过时的文字const view1 = chart.createView();   //创建view实例,View 是图层容器的概念,和ps中图层差不多,重叠顺序,没有重叠的图直接用chart就行view1.data(data1);  //绑定数据源view1.axis(false);  //不显示坐标轴view1.coordinate('polar', {      //坐标类型:极坐标innerRadius: 0.7,   //极坐标内半径radius: 100,  //极坐标半径  innerRadius,radius,以及假数据的20个数,可以调整其比例达到自己想要的间隙或者柱子宽度});view1.interval()   //Geom几何标记类型,interval:使用矩形或者弧形,用面积来表示大小关系的图形,一般构成柱状图、饼图等图表。//下面都是图形属性.position('type*value')  //坐标系映射.color(String(used), (cValue) => {   //颜色,支持字符串和这种写法,不接受变量,我试过了if (Number(cValue) >= 90) {return '#FBDBD9';} else if (Number(cValue) >= 70) {return '#FEF1DD';}return colors[0];})// .color('value',String(colors[0])).size(6);  //大小const view2 = chart.createView();   //图层二 同上view2.data(data2);view2.axis(false);view2.coordinate('polar', {innerRadius: 0.7,radius: 100,});view2.interval().position('type*value')// .color(String(colors[1])).color(String(used), (cValue) => {if (Number(cValue) >= 90) {return '#EF5C52';} else if (Number(cValue) >= 70) {return '#F8B755';}return colors[1];}).size(6);chart.render();    //渲染}, []);

b.柱状图(y轴分割线虚线,重叠,隔行显示文字)

const data = [{ type: 'this', info: '人脸搜索', value: 760 },{ type: 'this', info: '人体搜索', value: 520 },{ type: 'this', info: '机动车搜索', value: 820 },{ type: 'this', info: '非机动车搜索', value: 300 },];let max = 0;   //用来计算y坐标轴最高数值data.forEach((item) => {if (item.value > max) {max = item.value;}});let data1 = data.map((item) => {     //阴影灰色柱状图return { type: 'all', info: item.info, value: Math.ceil(max / 600) * 600 - item.value };});data.unshift(...data1);const chart = new Chart({container: 'container',autoFit: true,});chart.data(data);   //导入数据chart.interval().position('info*value').size(12).label('value', (xValue) => {    //显示文本内容return {content: xValue + '次',};}).color('type', ['#EEEEEE', '#2495FF'])//重叠.adjust('stack');  //设置数据调整方式,stack:层叠,第一个那个图表应该也可以用这个实现,稍微简单一点chart.axis('value', {      //坐标轴title: null,     // 不展示 xField 对应坐标轴的标题label: {       //隔行展示坐标轴文本formatter: (val) => {     // 使用 formatter 回调函数if ((Number(val) / 300) % 2 !== 0) {return '';} else {return val;}},},//网格虚线grid: {line: {style: {stroke: '#d9d9d9',lineWidth: 1,lineDash: [2, 2],},},},});chart.scale('value', {   //度量(Scale)用于定义数据的类型和展示方式nice: true,   //自动调整 min、max 。tickInterval: 300,    //控制间隔});//所有提示都不展示chart.tooltip(false);//所有图例都不展示chart.legend(false);//交互:鼠标在画布上移动是,对应的区域出现背景框chart.interaction('active-region');chart.render();

c.自定义图形柱状图(渐变,隔行换色,最大的感受G2文档太少了,不详细)

按照下面写法没法实现,我也不知道为什么,而且无法自适应了,奈何文档资料有限,百度都百度不到,没办法耗了半天天打算用Echarts重写…,但是G2写法也亮出来,请大家看看问题在哪里

G2:

import { Chart,registerShape } from '@antv/g2';
registerShape('interval', 'triangle', {   //注册自定义shape接口 getPoints(cfg:any) {        //  定义关键点const x = cfg.x;const y = cfg.y;const y0 = cfg.y0;const width = cfg.size;return [{ x: x - width / 2, y: y0 },{ x: x, y: y },{ x: x + width / 2, y: y0 },];},// 2. 绘制draw(cfg, group) {const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标//添加自定义shape ,实测其中image,dom类型,没法用,查不到为什么,官网也没有,那位大佬可以说一下为什么么?具体地址:https://g.antv.vision/zh/docs/api/canvasgroup.addShape('path', {     //采用路径方式attrs: {//这个路径就是< svg >< path d="............" >< /svg >  d中的值path:'M2.08269 86.5C28.1667 72.8126 45.3971 46.8239 48 17.6787C50.6029 46.8239 67.8333 72.8126 93.9173 86.5H2.08269Z',stroke:cfg.color,   //线条颜色lineWidth:2,   //线条宽度fill:cfg.color,  //填充颜色},});return group;},});const data = [{ type: 'this', info: '功能名称1', value: 1360 },{ type: 'this', info: '功能名称2', value: 1000 },{ type: 'this', info: '功能名称3', value: 980 },{ type: 'this', info: '功能名称4', value: 900 },{ type: 'this', info: '功能名称5', value: 860 },];let max = 0;data.forEach((item) => {if (item.value > max) {max = item.value;}});const chart = new Chart({container: 'container',autoFit: true,});chart.data(data);chart.interval().position('info*value').label('value', (xValue) => {return {content: xValue + '次',};}).size(100).color('info',(cVal)=>{let count=0;data.forEach((item,index)=>{if(item.info===cVal){count=index+1}});//隔行变色if(count%2!==0){//渐变写法return 'l(90) 0:rgba(36, 149, 255, 0.7) 1:rgba(36, 149, 255, 0.1)'}else{return 'l(90) 0:rgba(75, 215, 157, 0.7) 1:rgba(75, 215, 157, 0.1)'}}).shape('triangle');//坐标轴chart.axis('value', {// 不展示 xField 对应坐标轴的标题title: null,//网格虚线grid: {line: {style: {stroke: '#d9d9d9',lineWidth: 1,lineDash: [2, 2],},},},});//控制间隔chart.scale('value', {nice: true,tickInterval: 500,});//所有提示都不展示chart.tooltip(false);//所有图例都不展示chart.legend(false);//交互:鼠标在画布上移动是,对应的区域出现背景框chart.interaction('active-region');chart.render();

Echarts:

import EchartsReact from 'echarts-for-react';
const Chart5e1 =()=>{type data={name:string,value:number}[]let data:data = [{name:'指挥中心',value:770},{name:'科信',value:450},{name:'刑侦',value:300},{name:'XXX',value:255},{name:'情报',value:203},
]
let xAxisData:any=[];
let seriesData:any=[];
let max=0;
//因为边框也需要隔行变色,但是borderColor属性不支持函数方式,所以只能加到data中data.forEach((item: any, index: number) => {if (item.value > max) {max = item.value;}if (index % 2 !== 0) {seriesData.push({value: item.value,itemStyle: {borderColor: 'rgba(75, 215, 157, 0.7)',},});} else {seriesData.push({value: item.value,itemStyle: {borderColor: 'rgba(36, 149, 255, 0.7)',},});}xAxisData.push(item.name);});
const option = {tooltip : {trigger: 'axis',axisPointer : {            // 坐标轴指示器,坐标轴触发有效type : 'none'        // 默认为直线,可选为:'line' | 'shadow'},backgroundColor:'#405685',textStyle : {color: '#E5EDF5',decoration: 'none',fontSize: 12,},formatter:function(param){let tip = '';tip = param[0].name+': '+ param[0].value;return tip}},grid: {  //图表与外层div间距,可以理解为paddingtop: '8%',right: '10%',left: '15%',bottom: '15%'},xAxis: {    type: 'category',data: xAxisData,axisLine: {lineStyle: {color: '#C3C8CC'}},axisTick: {show: false},axisLabel: {color: '#000',textStyle: {fontSize: 12},formatter:function(value){var ret = "";//拼接加\n返回的类目项  var maxLength = 4;//每项显示文字个数  var valLength = value.length;//X轴类目项的文字个数  var rowN = Math.ceil(valLength / maxLength); //类目项需要换行的行数  if (rowN > 1)//如果类目项的文字大于5,{  var temp = "";//每次截取的字符串  var start = 0;//开始截取的位置  var end = maxLength;//结束截取的位置  temp = value.substring(start, end)+'\n'+value.substring(end, valLength)                  ret += temp; //凭借最终的字符串  return ret;  }else{return value;  }},},    splitLine: {show: false,}},yAxis: {type: 'value',axisLabel: {formatter: function (value: any) {return parseInt(value);},color: '#000',},max:Math.ceil(max/500)*500,interval:500,axisLine:{show:false},axisTick: {show: false},splitLine: {lineStyle: {type:'dashed',// 使用深浅的间隔色color: '#273858'}},},series: [{data: seriesData,type: 'pictorialBar',barCategoryGap: '-20%',symbol: 'path://M2.08269 86.5C28.1667 72.8126 45.3971 46.8239 48 17.6787C50.6029 46.8239 67.8333 72.8126 93.9173 86.5H2.08269Z',itemStyle: {normal: {//图形的间隔变色,渐变color:function(params){if(params.dataIndex % 2 == 0){return {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0, color: 'rgba(36, 149, 255, 0.7)' // 0% 处的颜色}, {offset: 1, color: 'rgba(36, 149, 255, 0.1)' // 100% 处的颜色}],globalCoord: false // 缺省为 false}}else{return {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0, color: 'rgba(75, 215, 157, 0.7)' // 0% 处的颜色}, {offset: 1, color: 'rgba(75, 215, 157, 0.1)' // 100% 处的颜色}],globalCoord: false // 缺省为 false}}}// color:{//   type: 'linear',//   x: 0,//   y: 0,//   x2: 0,//   y2: 1,//   colorStops: [{//       offset: 0, color: 'rgba(36, 149, 255, 0.7)' // 0% 处的颜色//   }, {//       offset: 1, color: 'rgba(36, 149, 255, 0.1)' // 100% 处的颜色//   }],//   globalCoord: false // 缺省为 false// }},},label: {normal: {show: true,position:'top',color:'#000',fontSize:14,formatter: function(params){var str = '';str = params.value;return str},fontFamily: 'DINPro'},},z: 10}, {name: 'glyph',type: 'pictorialBar',barGap: '-100%',symbolPosition: 'end',symbolSize: 50,symbolOffset: [0, '-120%'],}]
};return <EchartsReact option={option} style={{ width: '100%', height: '100%' }} />;
}
export default Chart5e1;

效果:

d.水波图组件(G2plot实现,个人感觉和G2没有太大区别)

组件:

import { useEffect, useRef, useState } from 'react';
import { Liquid } from '@antv/g2plot';//唯一id,颜色,数值,文本,大小
const LiquidChart=({ids,color,percent,textinfo,size})=>{const [liquidPlot,setLiquidPlot]=useState(null)useEffect(()=>{//数值更新销毁重绘if(liquidPlot!==null){liquidPlot.destroy()}const liquidPlot1 = new Liquid('sbchart'+ids, {    //新建percent: percent,  //百分比width:size,   height:size,liquidStyle:{    //水波样式fill:color,stroke:color},statistic :{      //文本配置title:{formatter:(v)=>{return v.percent*100+'%'},style:{fontSize:size/9,color: '#093049'}},content:{content:textinfo,style:{fontSize:size/15,color: '#093049'}}}});liquidPlot1.render(); setLiquidPlot(liquidPlot1)},[color,percent,textinfo,size])return <div id={'sbchart'+ids}></div>
}
export default LiquidChart

使用

 <LiquidChartids={1}color={"#A595FE"}percent={cpu}textinfo={"CPU使用率"}size={220}>
</LiquidChart>

e.曲线面积图表组件(G2plot实现)

组件

import { useEffect, useRef, useState } from 'react';
import { Line } from '@antv/g2plot';
const LineChart=({data,height,ids,legend=true,width,xAxis=true,yAxis=true})=>{const [linePlot1,setLinePlot1]=useState(null)useEffect(()=>{  //数值更新销毁重绘if(linePlot1!==null){linePlot1.destroy()}const linePlot = new Line('box'+ids, {data,padding:'auto',xField: 'date',  //x轴映射yField: 'value',   //y轴映射height:height,  seriesField: 'name',           //拆分字段,在分组条形图下同 groupField、colorField,在堆积条形图下同 stackField、colorField。width:width,yAxis: yAxis?{label: {formatter: (v) => `${v}`,},grid:{            line:{style:{lineDash:[4,5]          //设置轴线为虚线}}}}:false,xAxis: xAxis? {range: [0, 1],    //从x轴起点开始画,画到最后,不会存在与y轴存在间距label: {formatter: (v) => {return v},},}:false,legend: legend?{position: 'top-left',     //设置图例位置}:false,tooltip: {formatter: (datum) => {return { name: datum.name, value: datum.value + 'Mbps' };   //设置提示},},smooth: true,// 配置折线趋势填充area: {style: ({ name }) => {const { colors10 } = linePlot.chart.getTheme();return {fill:name === '接入宽带'? `l(90) 0.3:${colors10[0]} 1:rgba(255,255,255,0.2)`: `l(90) 0.3:${colors10[1]}  1:rgba(255,255,255,0.2)`,};},},animation: {appear: {animation: 'wave-in',duration: 3000,},},});linePlot.render();setLinePlot1(linePlot)},[data])return <div id={"box"+ids}></div>
}
export default LineChart

使用

const dataarr=[
{name: "输入宽带",date:'1s',value: 82},{name: "输出宽带",date:'1s',value: 150},{name: "输入宽带",date:'2s',value: 96},{name: "输出宽带",date:'2s',value:126},
]
<LineChartdata={dataarr}height={240}ids={1}></LineChart>

f.双向柱状图(G2plot实现)

const [max,setMax]=useState(0)
const devicedata = [
{ type: `单通道设备视频通道`, sales: 150,aname:1 },
{ type: `单通道设备视频通道`, sales: -15,aname:0 },
{ type: `多通道设备视频通道`, sales: 120,aname:2 },
{ type: `多通道设备视频通道`, sales: -120,aname:0 }
]
let max=0
devicedata.forEach(item=>{if(Math.abs(item.sales)>max){max=Math.abs(item.sales)}})
setMax(max)
useEffect(()=>{if(bar1!==null){bar1.destroy()}const bar = new Bar('container', {data:devicedata,xField: 'sales',yField: 'type',meta: {                  // sales映射的最大最小值sales: {max: max,            min: -max,        //防止出现数据只有正值,导致负值的半轴不显示}},legend: {position: 'top-left',},width:500,yAxis:{label:{formatter: (v) => {if(v==="多通道设备视频通道"){     //y轴文本换行return `多通道设备视频通道`}return `单通道设备视频通道`},},},xAxis:{grid:{line:{style:{lineDash:[4,5]     //x轴线虚线}}},barWidthRatio:0.2,  //柱子宽度seriesField: 'aname', // 部分图表使用 seriesField //设置正值不同类颜色不同,负值都为灰色color: ({ aname }) => {if(aname === 0){return '#8E9DAF';}else if(aname===1){return '#4DAAFF';}return '#13C2C2';},tooltip:{formatter: (datum) => {return { name: datum.aname!==0?'在线':'离线', value: Math.abs(datum.sales) };},title:(v)=>{return v.trim()+'(个)'}},legend:false,barBackground: {style: {fill: 'rgba(0,0,0,0.1)',borderRadius:50},},interactions: [{ type: 'active-region', enable: false }],});bar.render();setbar1(bar)},[devicedata,max])

**

g.曲线图(自定义面积渐变,自定义图例,自定义x绘画区域,边框)


const AreasplineChart = ({id,className}:{id:string,className?:string}) => {const data = [{"year": "1","value": 4055,"category": "人脸"},{"year": "1","value": 1756,"category": "人体"},{"year": "1","value": 5664,"category": "机动车"},{"year": "1","value": 6004,"category": "非机动车"},{"year": "2","value": 2106,"category": "人脸"},{"year": "2","value": 1783,"category": "人体"},{"year": "2","value": 5019,"category": "机动车"},{"year": "2","value": 1005,"category": "非机动车"},....    ........]const fillcolor = [{type:'人脸',color:'l(90) 0.1:rgba(77, 170, 255, 0.3)  1:rgba(255,255,255,0.1)',},{type:'人体',color:'l(90) 0.1:rgba(165, 149, 254, 0.3)  1:rgba(255,255,255,0.1)',},{type:'机动车',color:'l(90) 0.1:rgba(32, 203, 206, 0.3)  1:rgba(255,255,255,0.1)',},{type:'非机动车',color:'l(90) 0.1:rgba(255, 170, 91, 0.3)  1:rgba(255,255,255,0.1)'}]useEffect(()=>{const line = new Line('container'+id, {data,xField: 'year',yField: 'value',seriesField: 'category',appendPadding:[24,0,0,0],height:220,xAxis:{//去除x轴的刻度线tickLine:null//定义画图区域,默认从第一个刻度开始,这样设置会从0开始画//range: [0, 1],},yAxis: {label: {// 数值格式化为千分位formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`),},//y轴值的间隔tickInterval:2000,grid:{            line:{style:{lineDash:[4,5]          //设置轴线为虚线}}}},legend: {position: 'top-left',itemWidth:80,//自定义图例的图标形状marker:{//内置类型symbol:'square',style:(value)=>{return {fill: value.stroke,lineJoin: "round",lineWidth: 6,r: 2,stroke: value.stroke,}}}},//是否为圆滑曲线,false为折线图smooth: true,//设置线颜色color:['rgba(77, 170, 255, 1)','rgba(165, 149, 254, 1)','rgba(32, 203, 206, 1)','rgba(255, 170, 91, 1)'],// 配置折线趋势填充area: {style: ({category}) => {return {fill: fillcolor.filter(v=>v.type===category)[0].color};},},});line.render();},[])return (<div id={`container${id}`} className={className}></div>)
}

h.折线图(自定义背景,自定义节点样式)

const StockPendingChart = ({id}:{id:string}) => {let data:object[]=[]for(let i=0;i<24;i++){data.push({"year": `${i<10?'0'+i : i}:00`,"value": Math.random()*10000,"category": "人脸"});data.push({"year": `${i<10?'0'+i : i}:00`,"value": Math.random()*10000,"category": "人体"});data.push({"year": `${i<10?'0'+i : i}:00`,"value": Math.random()*10000,"category": "机动车"});data.push({"year": `${i<10?'0'+i : i}:00`,"value": Math.random()*10000,"category": "非机动车"});}const [typechart,setTypechart]=useState(null)useEffect(()=>{const line = new Line('container'+id, {data,xField: 'year',yField: 'value',seriesField: 'category',height:200,//可以理解为图表与图例之间那些的间距appendPadding:[24,0,0,0],xAxis: {nice: true,label: {formatter: (name) => name,},// 坐标轴线的配置项 null 表示不展示tickLine:null,grid: {line: {style: {//设置x轴的那个灰色背景lineWidth:42,stroke: 'rgba(239, 242, 244, 0.5)',},},},},yAxis: {label: {// 数值格式化为千分位formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`),},tickInterval:2000,grid:{            line:{style:{lineDash:[4,5]          //设置轴线为虚线}}}},legend: {position: 'top-left',marker:{symbol:'square',style:(value)=>{return {fill: value.stroke,lineJoin: "round",lineWidth: 6,r: 2,stroke: value.stroke,}}}},//配置折线图每个节点的样式point: {size: 5,style: {lineWidth: 1,fillOpacity: 1,},shape: 'circle'},// 配置折线线条颜色color:['rgba(77, 170, 255, 1)','rgba(165, 149, 254, 1)','rgba(32, 203, 206, 1)','rgba(255, 170, 91, 1)'],});line.render();},[])return (<div id={`container${id}`} style={{flex:'1'}}></div>)
}

I.环图(自定义图例样式,G2plot ,G2分别实现)

//G2plot 实现
import React, { useEffect, useState } from "react";
import { Pie } from "@antv/g2plot";
import { TransNumber } from "@src/pages/utils";export interface chartdata {type: string;value: number;
}const PieChart = ({ id, datasouce }: { id: string, datasouce: chartdata[] }) => {const [typechart, setTypechart] = useState<any>(null)useEffect(() => {if (typechart) {typechart.destroy()}const piePlot = new Pie('container'+id, {data:datasouce,height:260,legend:{//图例项水平布局layout: 'horizontal',position: 'right',offsetX:-20,//是否分页flipPage:false,//图例项水平间距itemSpacing:24,//图例项垂直间距itemMarginBottom:34,//图例与图形的占比maxWidthRatio:0.6,//图例图标marker:{symbol:'square'},itemWidth:120,//图例名itemName:{style:{fontSize:14}},//图例值itemValue:{//水平居右alignRight:true,formatter(text) {return TransNumber(datasouce?.filter(item=>item.type===text)[0].value)},style:{fontSize:14}}},//空白间距pieStyle:{lineWidth:6},angleField: 'value',colorField: 'type',radius: 0.6,innerRadius: 0.6,label: false,interactions: [{ type: 'element-selected' }, { type: 'element-active' }],statistic: undefined,});piePlot.render();setTypechart(piePlot)}, [datasouce])return (<div id={`container${id}`}></div>)
}export default PieChart
//G2 实现
const ChildrenTypeChart = () => {const [typechart,setTypechart]=useState(null)useEffect(()=>{if(typechart!==null){typechart.destroy()}const data = [{ type: '消费连接异常', value: 15 },{ type: '任务启动异常', value: 15 },{ type: '网络连接异常', value: 10 },{ type: '数据库异常', value: 10 },{ type: '服务自身异常', value: 10 },{ type: '其他', value: 10 },];// 可以通过调整这个数值控制分割空白处的间距,0-1 之间的数值const sliceNumber = 0.01;// 自定义 other 的图形,增加两条线registerShape('interval', 'slice-shape', {draw(cfg, container) {const points= cfg.points;let path = [];path.push(['M', points[0].x, points[0].y]);path.push(['L', points[1].x, points[1].y - sliceNumber]);path.push(['L', points[2].x, points[2].y - sliceNumber]);path.push(['L', points[3].x, points[3].y]);path.push('Z');path = this.parsePath(path);return container.addShape('path', {attrs: {fill: cfg.color,path,},});},});const chart = new Chart({container: 'container',autoFit: true,height: 300,width:270});chart.legend({flipPage:false,itemWidth:120});chart.data(data);chart.coordinate('theta', {radius: 0.55,innerRadius: 0.65,});chart.tooltip({showTitle: false,showMarkers: false,});chart.interval().adjust('stack').position('value').color('type').shape('slice-shape');chart.render();setTypechart(chart)},[])return (<div id="container"></div>)
}

J.柱状图(自定义背景)

import React, { useEffect, useState } from "react";
import { Column } from '@antv/g2plot';
export interface chartdata {name: string;value: number;type: string;
}
const ClounmChart = ({ id, datasouce }: { id: string, datasouce: chartdata[] }) => {const [typechart, setTypechart] = useState<any>(null)useEffect(() => {if (typechart) {typechart.destroy()}const stackedColumnPlot = new Column('container' + id, {data: datasouce,isStack: true, //是否累叠xField: 'name',height: 240,appendPadding:[20,0,0,0],yField: 'value',legend: {position: 'top-right',},xAxis: {nice: true,// 坐标轴线的配置项 null 表示不展示tickLine: null,grid: {line: {style: {lineWidth: 36, //背景宽度lineDash: [4, 4],  //背景虚线,不要这个就是第二张图stroke: 'rgba(238, 239, 243, 1)',  //背景颜色},},},},yAxis: {label: {// 数值格式化为千分位formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`),},// tickInterval:2000,grid: {line: {style: {lineDash: [4, 5]          //设置轴线为虚线}}}},seriesField: 'type',columnWidthRatio: 0.2,});stackedColumnPlot.render();setTypechart(stackedColumnPlot)}, [datasouce])return (<div id={`container${id}`}></div>)
}export default ClounmChart

K.分组柱状图(自定义形状样式,间距等)

import { useEffect, useState } from "react";
import { Column } from '@antv/g2plot';
const ColumnGroupChart = ({ id, currentDetail }: { id: string, currentDetail: any }) => {const [currentChart, setCurrentChart] = useState<any>(null)const types = ['数据消费数量', '数据转换成功数量', '数据转换失败数量 ', '数据入库成功数量', '数据入库失败数量']useEffect(() => {let data: any[] = []currentDetail?.detailData?.forEach((item: any) => {data.push({type: types[item.type-1],datatype: "人脸",value: item?.faceCount})data.push({type: types[item.type-1],datatype: "人体",value: item?.bodyCount})data.push({type: types[item.type-1],datatype: "机动车",value: item?.faceCount})data.push({type: types[item.type-1],datatype: "非机动车",value: item?.nomotorVehicleCount})});if (currentChart) {currentChart.destroy()}const column = new Column('container' + id, {data: data,xField: 'type',yField: 'value',height: 400,seriesField: 'datatype',isGroup: true,appendPadding: [24, 0, 0, 0],// intervalPadding:160,maxColumnWidth: 16,xAxis: {tickLine: null,},yAxis: {label: {// 数值格式化为千分位formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`),},grid: {line: {style: {lineDash: [4, 5]          //设置轴线为虚线}}}},legend: {position: 'top-left',marker: {symbol: 'square',style: (value) => {return {fill: value.fill,lineJoin: "round",lineWidth: 6,r: 2,stroke: value.fill,}}}},columnStyle: {radius: [20, 20, 20, 20],},columnBackground: {style: {fill: 'rgba(245, 245, 245, 1)'}},color: ['rgba(77, 170, 255, 1)', 'rgba(165, 149, 254, 1)', 'rgba(32, 203, 206, 1)', 'rgba(255, 170, 91, 1)'],});column.render();setCurrentChart(column)// eslint-disable-next-line react-hooks/exhaustive-deps}, [])return <div id={`container${id}`} style={{ marginTop: '40px' }}></div>
}
export default ColumnGroupChart

L.区间柱状图

import { Column } from '@antv/g2plot';const data = [{ type: '分类一', type1:'lon',values: [76, 100] },{ type: '分类一', type1:'bon',values: [0, 72] },{ type: '分类1', type1:'lon',values: [88, 168] },{ type: '分类1', type1:'bon',values: [0, 84] },{ type: '分类3', type1:'lon',values: [42, 196] },{ type: '分类3', type1:'bon',values: [0, 38] },{ type: '分类4', type1:'lon',values: [99, 111] },{ type: '分类4', type1:'bon',values: [0, 95] },{ type: '分类5', type1:'lon',values: [62, 160] },{ type: '分类5', type1:'bon',values: [0, 58] },
];const barPlot = new Column('container', {data,xField: 'type',yField: 'values',isRange: true,maxColumnWidth:32,seriesField: 'type1',
});barPlot.render();

React+G2 + G2plot 踩坑相关推荐

  1. native react ssh_React Native踩坑笔记(持续更新中...)

    最近发现市场上对React Native开发人员的需求挺多的,自己就想学习一下React Native,多一门技术,好将来买个好价位.嘿嘿! 在学习React Native中碰到了不少坑,再次记录下来 ...

  2. React Native 入门踩坑

    开发环境搭建及环境变量配置 开发rn第一步需要配置安卓环境 android studio下载地址: https://developer.android.google.cn/studio/archive ...

  3. React项目部署踩坑

    1. 文件路径问题,在 package.json中增加homepage 2.css中图片路径问题,建议直接用import的引入使用 import bgimg from './images/bg.jpg ...

  4. truffle unbox react 初始化踩坑

    truffle unbox react 初始化踩坑 1.文件位置引起的错误 一定要在package.json 所在文件夹下npm run start ,新版本一定要进入client文件夹再npm ru ...

  5. React Native之React Navigation踩坑

    自动重装系统之后,已经很长一段时间没有来写React Native了,今天空闲之余,决定重新配置React Native的开发环境,继续踩坑... React Native的开发环境配置狠简单,只要依 ...

  6. 丰田项目踩坑手记(REACT)

    丰田项目踩坑手记(REACT) 路由配置的时候:要引入hash路由不是browswer那个 路由参考网址:react-guide.github.io/react-route- 路由网址:reacttr ...

  7. python array赋值_从踩坑学Python内部原理(5):执行时机的差异

    (给Python开发者加星标,提升Python技能) 英文:Satwik Kansal,翻译:暮晨 Python开发者整理自 GitHub [导读]:Python 是一个设计优美的解释型高级语言,它提 ...

  8. eslint 无法格式化ts_vscode-eslint的踩坑实践--typescript无法格式化

    Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待 4999元包邮 去购买 > vscode-eslint的踩坑实践--typescript无法格式 ...

  9. Next.js踩坑入门系列(七) —— 其他相关知识

    Next.js踩坑入门系列 (一) Hello Next.js (二) 添加Antd && CSS (三) 目录重构&&再谈路由 (四) Next.js中期填坑 (五) ...

最新文章

  1. docker-3-常用命令(上)
  2. Python学习笔记: Python 标准库概览二
  3. oracle 去除重复的信息
  4. icoding复习1,2
  5. springboot+thymeleaf+pageHelper带条件分页查询
  6. 团队任务2:冲刺前的准备
  7. 【转载】JSON介绍
  8. RocketMq : 消费消息的两种方式 pull 和 push
  9. Spring Boot + Security + Thymeleaf + Activiti 快速开发平台项目
  10. C# .NET 使用DotNetZip开源类库 处理 压缩/解压 Zip 处理乱码情况
  11. .NET之我见系列 - 类型系统(上)
  12. Security+ 学习笔记51 风险分析
  13. Xcode常用的快捷键有哪些?
  14. 拓端tecdat|R语言 RevoScaleR的大规模数据集决策树模型应用案例
  15. 2021-08-06MATLAB深度学习简单应用
  16. Linux redis常用命令
  17. 2016.09.20回顾
  18. ImportError: cannot import name ‘_validate_lengths‘解决方法
  19. linux mint 使用软件管理器安装软件
  20. 数据结构软件测试,资讯详情-java常见数据结构-柠檬班-自动化测试-软件测试培训-自学官网...

热门文章

  1. 诗词格律[6] 词的格律
  2. 解决Apple Watch S7 突然之间耗电快、续航差的问题
  3. 程序猿,你也配吃10元的盒饭?
  4. 现在那个拦截捆绑软件比较好_捆绑您的收件箱以更好地开发
  5. yd什么意思_yd是什么单位?
  6. 容联云通讯—+springboot
  7. java怎么计算幂函数,java中幂指数值的运算代码解析
  8. 爬虫案例——爬取豆瓣排名及影评
  9. android手机内存创建文件夹,Android在内存问题中创建文件夹
  10. Linux文件管理-压缩和解压