Skip to content

Commit

Permalink
feat(scatter): 散点图支持color和shape同时映射图例字段 & 添加单测 (#2406)
Browse files Browse the repository at this point in the history
* feat(scatter): 散点图支持color和shape同时映射图例字段 & 添加单测

* feat(scatter): 散点图支持配置 shapeLegend & sizeLegend

* test(scatter-legend): 增加散点图图例用例(shapeLegend、sizeLegend) (#2446)

* feat(scatter): 散点图支持配置 shapeLegend & sizeLegend

* test(scatter-legend): 增加散点图图例用例(shapeLegend、sizeLegend)

Co-authored-by: visiky <736929286@qq.com>
Co-authored-by: elvira.zy <elvira.zy@alibaba-inc.com>

* fix(scatter): 优化散点图图例逻辑

默认配置 legend 时,展示 color 图例和 shape 图例
当 shapeLegend 为 false,强制关闭 shape 图例
shape 为 undefined 时,默认不会展示 shape 图例

* docs(scatter-legend): 散点图图例文档

* fix: 修改 cr  建议

* fix: cr 建议

Co-authored-by: elvira1112 <ranxi1112@gmail.com>
Co-authored-by: elvira.zy <elvira.zy@alibaba-inc.com>
  • Loading branch information
3 people authored Mar 23, 2021
1 parent bfd9e24 commit c7b7724
Show file tree
Hide file tree
Showing 9 changed files with 415 additions and 37 deletions.
2 changes: 1 addition & 1 deletion __tests__/bugs/issue-2122-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BidirectionalBar } from '../../src';
import { createDiv } from '../utils/dom';

describe('#2122', () => {
it('数据为空', async () => {
it('数据为空', () => {
const plot = new BidirectionalBar(createDiv(), {
data: [],
width: 400,
Expand Down
63 changes: 63 additions & 0 deletions __tests__/unit/plots/scatter/color-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,67 @@ describe('scatter', () => {

scatter.destroy();
});

const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data: [
{ x: 10, y: 10, type: 'one', city: 'beijing' },
{ x: 40, y: 10, type: 'two', city: 'beijing' },
{ x: 50, y: 10, type: 'one', city: 'hangzhou' },
{ x: 60, y: 10, type: 'two', city: 'hangzhou' },
{ x: 40, y: 10, type: 'three', city: 'hangzhou' },
],
xField: 'x',
yField: 'y',
colorField: 'type',
shapeField: 'city',
color: ['#e764ff', '#2b0033'],
shape: ['circle', 'square'],
});

scatter.render();

it('color mapping with shape mapping', () => {
const geometry = scatter.chart.geometries[0];
const elements = geometry.elements;

// @ts-ignore
expect(geometry.attributeOption.color.values.length).toBe(2);
expect(elements.length).toBe(5);
expect(elements[0].getModel().color).not.toBe('red');
expect(elements[0].getModel().color).toBe('#e764ff');
expect(elements[0].shape.attr('fill')).toBe('#e764ff');
expect(elements[0].getModel().shape).toBe('circle');
expect(elements[2].getModel().shape).toBe('square');
});

it('color mapping with shape mapping, colorAttr is callback', () => {
scatter.update({
color: ({ type }) => {
return type === 'three' ? 'red' : undefined;
},
});
const geometry = scatter.chart.geometries[0];
const elements = geometry.elements;

expect(elements.length).toBe(5);
expect(elements[4].shape.attr('fill')).toBe('red');
expect(elements[0].shape.attr('fill')).toBe(scatter.chart.getTheme().colors10[0]);
expect(elements[0].getModel().shape).toBe('circle');
expect(elements[2].getModel().shape).toBe('square');
});

it('color mapping with shape mapping, legends', () => {
scatter.update({ shapeLegend: {} });
const legendController = scatter.chart.getController('legend');
expect(legendController.getComponents().length).toBe(2);
expect(legendController.getComponents()[0].component.get('items').length).toBe(3);
expect(legendController.getComponents()[1].component.get('items').length).toBe(2);
});

afterAll(() => {
scatter.destroy();
});
});
158 changes: 152 additions & 6 deletions __tests__/unit/plots/scatter/legend-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@ describe('scatter', () => {
const legendController = scatter.chart.getController('legend');
// @ts-ignore
const { option } = legendController;
expect(option).toBe(false);
expect(option).toEqual({ height: false, weight: false });
scatter.update({
shapeField: 'gender',
});
// @ts-ignore
expect(scatter.chart.getController('legend').option).toEqual({
gender: undefined,
height: false,
weight: false,
});
expect(scatter.chart.getController('legend').option).toEqual({ height: false, weight: false });

expect(legendController.getComponents().length).toBe(1);

scatter.update({
shapeField: '',
colorField: 'g',
Expand Down Expand Up @@ -197,4 +196,151 @@ describe('scatter', () => {

scatter.destroy();
});

it('shapeLegend: shapeField * {}', () => {
const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data,
xField: 'weight',
yField: 'height',
shapeField: 'gender',
shapeLegend: {},
xAxis: {
nice: true,
},
});

scatter.render();
const legendController = scatter.chart.getController('legend');
// @ts-ignore
expect(legendController.option).toMatchObject({
gender: {},
});

scatter.destroy();
});

it('shapeLegend: legend * shapeField * false', () => {
const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data,
xField: 'weight',
yField: 'height',
shapeField: 'gender',
shapeLegend: false,
colorField: '',
xAxis: {
nice: true,
},
legend: {},
});

scatter.render();
const legendController = scatter.chart.getController('legend');
// @ts-ignore
expect(legendController.option).toEqual({
gender: false,
height: false,
weight: false,
});

scatter.destroy();
});

it('sizeLegend: sizeField * {}', () => {
const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data,
xField: 'weight',
yField: 'height',
sizeField: 'weight',
sizeLegend: {},
xAxis: {
nice: true,
},
});

scatter.render();
const legendController = scatter.chart.getController('legend');
// @ts-ignore
expect(legendController.option).toEqual({
height: false,
weight: {},
});

scatter.destroy();
});

it('sizeLegend: legend * sizeField * false', () => {
const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data,
xField: 'weight',
yField: 'height',
sizeField: 'weight',
sizeLegend: false,
colorField: '',
xAxis: {
nice: true,
},
legend: {},
});

scatter.render();
const legendController = scatter.chart.getController('legend');
// @ts-ignore
expect(legendController.option).toEqual({
height: false,
weight: false,
});
});

const scatter = new Scatter(createDiv(), {
width: 400,
height: 300,
appendPadding: 10,
data: data.map((d) => ({ ...d, ['gender-1']: d.gender })),
xField: 'weight',
yField: 'height',
shapeField: 'gender',
xAxis: {
nice: true,
},
});

scatter.render();

it('not colorField, but shapeField, legend 会取 shapeField', () => {
const legendController = scatter.chart.getController('legend');
expect(legendController.getComponents().length).toBe(1);
expect(legendController.getComponents()[0].id).toBe('legend-gender');
});

it('shapeLegend toBe false', () => {
scatter.update({ shapeLegend: false });
const legendController = scatter.chart.getController('legend');
expect(legendController.getComponents().length).toBe(0);
});

it('当 colorField & shapeLegend 同字段时,shapeLegend false 会导致 colorLegend 关闭', () => {
scatter.update({ colorField: 'gender', shapeLegend: {} });
let legendController = scatter.chart.getController('legend');
expect(legendController.getComponents().length).toBe(1);

scatter.update({ shapeLegend: false });
legendController = scatter.chart.getController('legend');
expect(legendController.getComponents().length).toBe(0);
});

afterAll(() => {
scatter.destroy();
});
});
68 changes: 59 additions & 9 deletions docs/api/plots/scatter.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,22 @@ Adjust types provided by G2Plot includes 'stack', 'dodge' 'jitter', 'symmetric'.

The name of the data field corresponding to the dot color map.

### Geometry Style
#### shapeField

`markdown:docs/common/color.en.md`
<description>**optional** _string_</description>

The name of the data field corresponding to the dot shape map.

#### sizeField

<description>**optional** _string_</description>

The name of the data field corresponding to the point size map.

### Geometry Style

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

#### size

<description>**optional** \_number | [number, number] | Function\_</description>
Expand Down Expand Up @@ -103,12 +109,6 @@ Specifies the size of the point. If no sizeField is configured, specify one. Whe
}
```

#### shapeField

<description>**optional** _string_</description>

The name of the data field corresponding to the dot shape map.

#### shape

<description>**optional** \_string | string[] | Function\_</description>
Expand Down Expand Up @@ -191,7 +191,57 @@ Default configuration:

### Plot Components

`markdown:docs/common/component.en.md`
#### tooltip

`markdown:docs/common/tooltip.en.md`

#### label

`markdown:docs/common/label.en.md`

#### axis

Same for xAxis and yAxis. **Note**: Since `DualAxes` or `BidirectionalBar` has double Y-axes, the yAxis is a object which takes the field in yField as the 'key'.

`markdown:docs/common/axis.en.md`

#### legend

<description>**optional** _false | LegendCfg_</description>

```sign
When colorField existed and legend is not false, color legend will be rendered.
When shapeField existed and legend is not false, shape legend will be rendered. You can set `shapeLegend: false` to hide shape legend.
```

`markdown:docs/common/legend.en.md`

#### shapeLegend

<description>**optional** _false | LegendCfg_</description>

```sign
当 shapeField 存在时,且 legend 不为 false 以及 shapeLegend 不为 false,默认会渲染 shape 映射图例。
1、你可以通过设置 `shapeLegend: false` 来隐藏 shape 图例。
2、你也可以通过定义 `shapeLegend` 来对 shape 图例进行配置。
```

Details to see: [legend](#legend)

#### sizeLegend

<description>**optional** _false | LegendCfg_</description>

```sign
Default size legend is not shown, only when `sizeField` and `sizeLegend` existed,size legend will be shown。
```

Details to see: [legend](#legend)

#### annotations

`markdown:docs/common/annotations.en.md`

#### quadrant

Expand Down
Loading

0 comments on commit c7b7724

Please sign in to comment.