Skip to content

Commit

Permalink
feat(venn): 韦恩图颜色回调重构 (#2909)
Browse files Browse the repository at this point in the history
* feat(venn): 韦恩图颜色回调重构

1. 修复 color 设置回调,导致图例颜色不正确
2. color 回调参数,增加 defaultColor 默认色
3. 完善韦恩图文档 & 增加 demo

* test(venn): 韦恩图单测

fix: #2906

* test(venn): 添加韦恩图 color 单测
  • Loading branch information
visiky committed Oct 14, 2021
1 parent 994c75d commit c369496
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 22 deletions.
28 changes: 28 additions & 0 deletions __tests__/bugs/issue-2906-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Venn } from '../../src';
import { createDiv } from '../utils/dom';

describe('#2906', () => {
it('venn plot color callback', () => {
const plot = new Venn(createDiv(), {
setsField: 'sets',
sizeField: 'size',
data: [
{ sets: ['A'], size: 12, label: 'A' },
{ sets: ['B'], size: 12, label: 'B' },
{ sets: ['C'], size: 12, label: 'C' },
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
{ sets: ['B', 'C'], size: 2, label: 'B&C' },
{ sets: ['A', 'B', 'C'], size: 1 },
],
pointStyle: { fillOpacity: 0.85 },
color: (datum) => (datum.sets?.length === 1 ? 'blue' : 'red'),
});
plot.render();

const legendController = plot.chart.getController('legend');
const items = legendController.getComponents()[0].component.get('items');
expect(items[0].marker.style.fill).toBe('blue');
expect(items[3].marker.style.fill).toBe('red');
});
});
23 changes: 23 additions & 0 deletions __tests__/unit/plots/venn/color-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,29 @@ describe('venn: color', () => {
expect(plot.chart.geometries[0].elements[5].getModel().color).toBe('blue');
});

it('color: callback params', () => {
plot.update({
theme: { colors10: ['red', 'yellow', 'blue'] },
color: undefined,
});

expect(plot.chart.geometries[0].elements[0].getModel().color).toBe('red');
expect(plot.chart.geometries[0].elements[1].getModel().color).toBe('yellow');
expect(plot.chart.geometries[0].elements[2].getModel().color).toBe('blue');
expect(plot.chart.geometries[0].elements[4].getModel().color).not.toBe('black');

plot.update({
color: (datum, defaultColor) => {
return ['red', 'blue'].indexOf(defaultColor) === -1 ? 'black' : defaultColor;
},
});
expect(plot.chart.geometries[0].elements[0].getModel().color).toBe('red');
expect(plot.chart.geometries[0].elements[1].getModel().color).not.toBe('yellow');
expect(plot.chart.geometries[0].elements[1].getModel().color).toBe('black');
expect(plot.chart.geometries[0].elements[2].getModel().color).toBe('blue');
expect(plot.chart.geometries[0].elements[4].getModel().color).toBe('black');
});

afterAll(() => {
plot.destroy();
});
Expand Down
29 changes: 28 additions & 1 deletion docs/api/plots/venn.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,34 @@ The name of the data field corresponding to the point size map.

### Geometry Style

`markdown:docs/common/color.en.md`
#### color

<description>**optional** _string | string[] | Function_</description>

指定图形元素的颜色。可以指定单色,或者一系列色值,也可以通过回调函数的方法根据对应数值进行设置。(**注意**:韦恩图的 color 系列色值只作用于单个集合上,交集部分通过指定 blendMode 来进行叠加处理。另外,color 回调中,第二个参数代表默认分配的颜色。)

默认配置:采用 theme 中的色板。演示 [Demo](/zh/examples/more-plots/venn#blend-mode)

```ts
// 设置单一颜色
{
color: '#a8ddb5'
}
// 设置多色
{
color: ['#d62728', '#2ca02c', '#000000'],
}
// Function
{
color: (datum, defaultColor) => {
if(datum.size > 100){
return 'red';
}
return defaultColor;
}
}
```


#### blendMode

Expand Down
29 changes: 27 additions & 2 deletions docs/api/plots/venn.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,33 @@ order: 12

### 图形样式

<!-- Color 配置 -->
`markdown:docs/common/color.zh.md`
#### color

<description>**optional** _string | string[] | Function_</description>

指定图形元素的颜色。可以指定单色,或者一系列色值,也可以通过回调函数的方法根据对应数值进行设置。(**注意**:韦恩图的 color 系列色值只作用于单个集合上,交集部分通过指定 blendMode 来进行叠加处理。另外,color 回调中,第二个参数代表默认分配的颜色。)

默认配置:采用 theme 中的色板。演示 [Demo](/zh/examples/more-plots/venn#blend-mode)

```ts
// 设置单一颜色
{
color: '#a8ddb5'
}
// 设置多色
{
color: ['#d62728', '#2ca02c', '#000000'],
}
// Function
{
color: (datum, defaultColor) => {
if(datum.size > 100){
return 'red';
}
return defaultColor;
}
}
```

#### blendMode

Expand Down
6 changes: 6 additions & 0 deletions docs/manual/plots/venn.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Venn
order: 30
---

`markdown:docs/manual/plots/venn.zh.md`
35 changes: 35 additions & 0 deletions docs/manual/plots/venn.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: 韦恩图
order: 30
---

<iframe width="100%" height="500" frameborder="0" allowfullscreen style="border:1px solid #d9d9d9;" src="https://www.yuque.com/antv/g2plot/venn-guide?view=doc_embed">
## 快速上手
<div class="sign">
```ts
import { Venn } from '@antv/g2plot';
const plot = new Venn('container', {
data: [
{ sets: ['A'], size: 12, label: 'A' },
{ sets: ['B'], size: 12, label: 'B' },
{ sets: ['C'], size: 12, label: 'C' },
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
{ sets: ['B', 'C'], size: 2, label: 'B&C' },
{ sets: ['A', 'B', 'C'], size: 1 },
],
setsField: 'sets',
sizeField: 'size',
});
plot.render();
```
</div>
📊 查看更多<a href="/zh/examples/more-plots/venn#basic" target='blank'>示例</a>.
🎨 韦恩图详细的配置参考 [API 文档](/zh/docs/api/plots/venn)。
23 changes: 23 additions & 0 deletions examples/more-plots/venn/demo/color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Venn } from '@antv/g2plot';

const plot = new Venn('container', {
data: [
{ sets: ['A'], size: 102, label: 'A' },
{ sets: ['B'], size: 12, label: 'B' },
{ sets: ['C'], size: 12, label: 'C' },
{ sets: ['A', 'B'], size: 2, label: 'A&B' },
{ sets: ['A', 'C'], size: 2, label: 'A&C' },
{ sets: ['B', 'C'], size: 2, label: 'B&C' },
{ sets: ['A', 'B', 'C'], size: 1 },
],
setsField: 'sets',
sizeField: 'size',
pointStyle: { fillOpacity: 0.85 },
color: (datum, defaultColor) => {
if (datum.size > 100) {
return '#FF4500';
}
return defaultColor;
},
});
plot.render();
16 changes: 9 additions & 7 deletions examples/more-plots/venn/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"zh": "基础韦恩图",
"en": "Basic venn plot"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png"
},
{
Expand All @@ -19,16 +18,22 @@
"zh": "设置颜色叠加模式",
"en": "Color blend mode"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/XZE3uS3Ezm/e18cdf57-f528-4a43-a0a5-b92dba819477.png"
},
{
"filename": "color.ts",
"title": {
"zh": "自定义颜色",
"en": "Custom color"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/jonq4FL0vL/7b5db090-a855-4861-806f-5e09c2fdfd97.png"
},
{
"filename": "tooltip.ts",
"title": {
"zh": "格式化 tooltip",
"en": "Formatter tooltip"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/BJw8fy6uxU/009dd50e-c2a4-48dc-a79a-dc417123889f.png"
},
{
Expand All @@ -37,7 +42,6 @@
"zh": "设置 label",
"en": "Label setting"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/nyPJ6bGZ68/d5e85b5d-70c5-45b5-94aa-9a229e65474c.png"
},
{
Expand All @@ -46,7 +50,6 @@
"zh": "自定义韦恩图",
"en": "Customize venn plot"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/T6cgHx5BHB/f2137e3b-5784-4626-a986-109fc8cb5feb.png"
},
{
Expand All @@ -55,8 +58,7 @@
"zh": "韦恩图 - 元素交互",
"en": "venn plot - with element action"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/x%24Jxds2L2T/0ff5000b-d23e-49a8-a02a-4eb02d7a8e47.png"
}
]
}
}
40 changes: 30 additions & 10 deletions src/plots/venn/adaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,32 @@ import './interaction';
/** 图例默认预留空间 */
export const LEGEND_SPACE = 40;

/**
* 获取 color 映射
*/
function colorMap(params: Params<VennOptions>, data: VennData, colorPalette?: string[]) {
const { chart, options } = params;
const { setsField } = options;
const { colors10, colors20 } = chart.getTheme();
let palette = colorPalette;
if (!isArray(palette)) {
palette = data.filter((d) => d[setsField].length === 1).length <= 10 ? colors10 : colors20;
}
const colorMap = getColorMap(palette, data, options);

return (id: string) => colorMap.get(id) || palette[0];
}

/**
* color options 转换
*/
function transformColor(params: Params<VennOptions>, data: VennData): VennOptions['color'] {
const { chart, options } = params;
const { color, setsField } = options;
const { options } = params;
const { color } = options;

if (typeof color !== 'function') {
let colorPalette = typeof color === 'string' ? [color] : color;
if (!isArray(colorPalette)) {
const { colors10, colors20 } = chart.getTheme();
colorPalette = data.filter((d) => d[setsField].length === 1).length <= 10 ? colors10 : colors20;
}
const colorMap = getColorMap(colorPalette, data, options);
return (datum: Datum) => colorMap.get(datum[ID_FIELD]) || colorPalette[0];
const colorPalette = typeof color === 'string' ? [color] : color;
return (datum: Datum) => colorMap(params, data, colorPalette)(datum[ID_FIELD]);
}
return color;
}
Expand Down Expand Up @@ -132,7 +143,6 @@ function geometry(params: Params<VennOptions>): Params<VennOptions> {
schema: {
shape: 'venn',
style: pointStyle,
color: transformColor(params, vennData),
},
},
})
Expand All @@ -141,6 +151,16 @@ function geometry(params: Params<VennOptions>): Params<VennOptions> {
const geometry = ext.geometry as Geometry;
geometry.customInfo(customInfo);

const colorOptions = transformColor(params, vennData);
// 韦恩图试点, color 通道只能映射一个字段. 通过外部查找获取 datum
if (typeof colorOptions === 'function') {
geometry.color(ID_FIELD, (id) => {
const datum = vennData.find((d) => d[ID_FIELD] === id);
const defaultColor = colorMap(params, vennData)(id);
return colorOptions(datum, defaultColor);
});
}

return params;
}

Expand Down
4 changes: 2 additions & 2 deletions src/plots/venn/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Types } from '@antv/g2';
import { Options, StyleAttr } from '../../types';
import { Datum, Options, StyleAttr } from '../../types';
import { ID_FIELD, PATH_FIELD } from './constant';

export type VennData = (Types.Datum & { sets: string[]; [PATH_FIELD]: string; [ID_FIELD]: string })[];
Expand All @@ -15,7 +15,7 @@ export interface VennOptions extends Options {

// 韦恩图 样式
/** color */
readonly color?: Options['color'];
readonly color?: string | string[] | ((datum: Datum, defaultColor: string) => string);
/** 并集合的颜色混合方式, 可选项: 参考 https://gka.github.io/chroma.js/#chroma-blend, 默认: multiply */
readonly blendMode?: string;
/** point 样式 */
Expand Down

0 comments on commit c369496

Please sign in to comment.