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.promises.top/posts/front/drawing-venn-diagrams-with-antv-g2/