847 字
4 分钟
使用 antv/g2 绘制双圈交集图形
最近在开发新项目,但是这个项目由其他部门搭建的,使用了和我们原先不同的图表图。我们组原先使用的是 echarts 而这个项目使用的是 antv/g2 ,由于之前并没有使用过这个图表图,特此记录一下
乍一看觉得这个实现起来并不复杂,使用韦恩图即可实现,随即上官网查看韦恩图示例,一步步修改配置,最终实现出来如下样子的图
实现代码如下
chart .path() .data({ type: 'inline', value: [ { sets: ['A'], size: 15, label: '购买人数', value: 19992 }, { sets: ['B'], size: 15, label: '会员总数', value: 29992 }, { sets: ['A', 'B'], size: 6, label: '会员购买人数', value: 9992 }, ], transform: [ { type: 'venn', }, ], }) .encode('d', 'path') .encode('color', 'key') .encode('shape', 'hollow') .label({ position: 'inside', text: (a) => `${a?.label}\n${formatNumOfOptions(a?.value, { digit: 0 })}`, style: { fontSize: 12, fontWeight: 500, fill: '#1890FF', }, }) .style('lineWidth', 1) .style('lineDash', [7, 4]) .style('fill', (d) => { if (d.sets.length === 1) { if (d.sets[0] === 'A') { return '#3BA0FF'; } return '#4DCB73'; } return '#cdecf2'; }) .style('fillOpacity', 0.1) .legend(false) .tooltip(false);
观察上图很容易看出这与设计图有两处不同,分别是交汇处的线条颜色,以及 label 的位置
首先解决交汇处线条颜色,让它们在交汇处仍然用自身原本的颜色,使用 style 实现,代码如下
style('stroke', (d) => { if (d.key === 'A') { return '#1890FF'; } if (d.key === 'B') { return '#4DCB73'; } return 'transparent';})
而解决 label 位置就稍微麻烦一些,需要自定义渲染 label ,查了下文档,发现自定义渲染使用 label.render 函数
使用 render 函数自定义渲染 html 标签,配合 css 属性transform: translate 进行偏移最终实现标签的自定义位置,具体实现代码如下
render: (_, datum) => { if (datum.key === 'A') { return ` <div style="font-weight: 500; color: #1890FF; transform: translate(-80px, -20px)"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `; } if (datum.key === 'B') { return ` <div style="font-weight: 500; color: #4DCB73; transform: translate(30px, -20px);"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `; } return ` <div style="font-weight: 500; color: #00BBFF; transform: translate(-36px, -20px);"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `;}
这时你会发现虽然 label 标签正确的进行了偏移但是在偏移原点时会出现蓝色方块,如下图所示
这是因为使用了CSS来样式化标签,将 label.style.fill 属性删除即可,最终代码如下
const chart = new Chart({ container: 'user-assets', height: 311, });
chart .path() .data({ type: 'inline', value: [ { sets: ['A'], size: 15, label: '购买人数', value: 19992 }, { sets: ['B'], size: 15, label: '会员总数', value: 29992 }, { sets: ['A', 'B'], size: 6, label: '会员购买人数', value: 9992 }, ], transform: [ { type: 'venn', }, ], }) .encode('d', 'path') .encode('color', 'key') .encode('shape', 'hollow') .label({ position: 'inside', text: (a) => `${a?.label}\n${formatNumOfOptions(a?.value, { digit: 0 })}`, style: { fontSize: 12, }, render: (_, datum) => { if (datum.key === 'A') { return ` <div style="font-weight: 500; color: #1890FF; transform: translate(-80px, -20px)"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `; } if (datum.key === 'B') { return ` <div style="font-weight: 500; color: #4DCB73; transform: translate(30px, -20px);"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `; } return ` <div style="font-weight: 500; color: #00BBFF; transform: translate(-36px, -20px);"> <p style="font-size: 12px">${datum.label}</p> <p style="font-size: 14px">${formatNumOfOptions(datum.value, { digit: 0 })}</p> </div> `; }, }) .style('lineWidth', 1) .style('lineDash', [7, 4]) .style('fill', (d) => { if (d.sets.length === 1) { if (d.sets[0] === 'A') { return '#3BA0FF'; } return '#4DCB73'; } return '#cdecf2'; }) // 交汇处描边的线条颜色维持它们各自的颜色 .style('stroke', (d) => { if (d.key === 'A') { return '#1890FF'; } if (d.key === 'B') { return '#4DCB73'; } return 'transparent'; }) .style('fillOpacity', 0.1) .legend(false) .tooltip(false); chart.render();
使用 antv/g2 绘制双圈交集图形
https://www.mihouo.com/posts/front/drawing-venn-diagrams-with-antv-g2/