Skip to content

Commit ac17235

Browse files
authored
feat: changedata (#2142)
* docs(line-demo): 优化基础折线图 demo * feat(core): plot core 提供 updateOptions 方法 & 提供 changedata 复写 * feat(line): 折线图支持动态更新数据 - overrider changedata - provide demo * feat(gauge): 仪表盘支持动态更新数据 - 抽取获取 view data 的工具方法 - override changeData * feat(gauge): 优化仪表盘的 changedata, 每一次 changedata 只做一次 paint 绘制 - [x] 单测 * fix(gauge): 修改文档 & demo * feat(🔨): 增加测试用例 * feat(gauge): 添加仪表盘 utils 测试用例 * fix: 修改 cr 建议 * docs: 更新网站 demo 截图
1 parent 5de3aca commit ac17235

File tree

19 files changed

+421
-42
lines changed

19 files changed

+421
-42
lines changed

__tests__/unit/core/index-spec.ts

+35-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,40 @@ describe('core', () => {
4040
line.destroy();
4141
});
4242

43+
it('updateOption without render', () => {
44+
const options = {
45+
width: 400,
46+
height: 300,
47+
data: [
48+
{ date: '12-01', value: 1, type: 'bb' },
49+
{ date: '12-02', value: 12, type: 'bb' },
50+
],
51+
xField: 'date',
52+
yField: 'value',
53+
seriesField: 'type',
54+
};
55+
const line = new Line(createDiv(), options);
56+
57+
line.render();
58+
59+
// @ts-ignore
60+
line.updateOption({
61+
data: [...line.options.data, { date: '12-01', value: 4, type: 'cc' }, { date: '12-02', value: 19, type: 'cc' }],
62+
});
63+
64+
expect(line.chart.geometries[0].elements.length).toBe(1);
65+
66+
line.render();
67+
expect(line.chart.geometries[0].elements.length).toBe(2);
68+
69+
line.update({
70+
data: [...line.options.data, { date: '12-01', value: 4, type: 'dd' }, { date: '12-02', value: 19, type: 'dd' }],
71+
});
72+
expect(line.chart.geometries[0].elements.length).toBe(3);
73+
74+
line.destroy();
75+
});
76+
4377
it('update mix with default options', () => {
4478
const options = {
4579
width: 400,
@@ -53,9 +87,7 @@ describe('core', () => {
5387
line.render();
5488
const curOptions = clone(line.options);
5589

56-
line.update({ ...options, width: 500 });
57-
58-
line.render();
90+
line.update({ width: 500 });
5991

6092
expect(isEqual(line.options, deepMix(curOptions, { ...options, width: 500 }))).toBeTruthy();
6193

__tests__/unit/plots/gauge/index-spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Gauge } from '../../../../src';
2+
import { INDICATEOR_VIEW_ID, RANGE_VIEW_ID } from '../../../../src/plots/gauge/constant';
23
import { pick } from '../../../../src/utils';
34
import { createDiv } from '../../../utils/dom';
45

@@ -114,6 +115,8 @@ describe('gauge', () => {
114115
});
115116

116117
gauge.render();
118+
expect(gauge.chart.views[0].id).toEqual(INDICATEOR_VIEW_ID);
119+
expect(gauge.chart.views[1].id).toEqual(RANGE_VIEW_ID);
117120
// @ts-ignore
118121
expect(gauge.chart.views[1].getYScales()[0].ticks).toEqual([0, 0.25, 0.5, 0.75, 1]);
119122
expect(gauge.chart.views.length).toBe(2);
@@ -141,6 +144,7 @@ describe('gauge', () => {
141144

142145
gauge.render();
143146

147+
expect(gauge.chart.views[0].id).toEqual(RANGE_VIEW_ID);
144148
expect(gauge.chart.views.length).toBe(1);
145149
expect(gauge.chart.views[0].geometries[0].type).toBe('interval');
146150

__tests__/unit/plots/gauge/statistic-spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ describe('gauge statistic', () => {
4444
expect((annotations[0] as HTMLElement).innerText).toBe('测试');
4545
});
4646

47+
it('change data', () => {
48+
gauge.changeData(0.35);
49+
const annotations = document.body.querySelectorAll('.g2-html-annotation');
50+
expect(annotations.length).toBe(2);
51+
expect((annotations[1] as HTMLElement).innerText).toBe('35.0%');
52+
53+
gauge.changeData(0.15);
54+
expect((document.body.querySelectorAll('.g2-html-annotation')[1] as HTMLElement).innerText).toBe('15.0%');
55+
56+
gauge.update({ statistic: { content: {}, title: false } });
57+
expect(document.body.querySelectorAll('.g2-html-annotation').length).toBe(1);
58+
expect((document.body.querySelectorAll('.g2-html-annotation')[0] as HTMLElement).innerText).toBe('15.0%');
59+
60+
gauge.changeData(0.05);
61+
expect((document.body.querySelectorAll('.g2-html-annotation')[0] as HTMLElement).innerText).toBe('5.0%');
62+
});
63+
4764
afterAll(() => {
4865
gauge.destroy();
4966
});
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { PERCENT, RANGE_TYPE, RANGE_VALUE } from '../../../../src/plots/gauge/constant';
2+
import { getIndicatorData, getRangeData } from '../../../../src/plots/gauge/utils';
3+
4+
describe('gauge utils to getData', () => {
5+
it('get indicatorData', () => {
6+
expect(getIndicatorData(0.1)).toEqual([{ [PERCENT]: 0.1 }]);
7+
expect(getIndicatorData(1.4)).toEqual([{ [PERCENT]: 1 }]);
8+
expect(getIndicatorData(-0.4)).toEqual([{ [PERCENT]: 0 }]);
9+
});
10+
11+
it('get rangeData', () => {
12+
expect(getRangeData(0.5, { ticks: [0, 0.3, 1] })).toEqual([
13+
{ [RANGE_VALUE]: 0.3, [RANGE_TYPE]: '1' },
14+
{ [RANGE_VALUE]: 0.7, [RANGE_TYPE]: '2' },
15+
]);
16+
17+
expect(getRangeData(0.5)).toEqual([
18+
{ [RANGE_VALUE]: 0.5, [RANGE_TYPE]: '1' },
19+
{ [RANGE_VALUE]: 0.5, [RANGE_TYPE]: '2' },
20+
]);
21+
22+
expect(getRangeData(-0.5)).toEqual([{ [RANGE_VALUE]: 1, [RANGE_TYPE]: '2' }]);
23+
expect(getRangeData(1.5)).toEqual([{ [RANGE_VALUE]: 1, [RANGE_TYPE]: '1' }]);
24+
25+
expect(getRangeData(0)).toEqual([{ [RANGE_VALUE]: 1, [RANGE_TYPE]: '2' }]);
26+
expect(getRangeData(1)).toEqual([{ [RANGE_VALUE]: 1, [RANGE_TYPE]: '1' }]);
27+
});
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Line } from '../../../../src';
2+
import { partySupport } from '../../../data/party-support';
3+
import { createDiv } from '../../../utils/dom';
4+
5+
describe('line', () => {
6+
it('change data', () => {
7+
const line = new Line(createDiv(), {
8+
width: 400,
9+
height: 300,
10+
data: partySupport.filter((o) => ['FF'].includes(o.type)),
11+
xField: 'date',
12+
yField: 'value',
13+
seriesField: 'type',
14+
color: ['blue', 'red'],
15+
appendPadding: 10,
16+
connectNulls: true,
17+
});
18+
19+
line.render();
20+
21+
expect(line.chart.geometries[0].elements.length).toBe(1);
22+
23+
line.changeData(partySupport.filter((o) => ['FF', 'Lab'].includes(o.type)));
24+
expect(line.chart.geometries[0].elements.length).toBe(2);
25+
expect(line.options.data).toEqual(partySupport.filter((o) => ['FF', 'Lab'].includes(o.type)));
26+
27+
line.destroy();
28+
});
29+
30+
it('add point', () => {
31+
const line = new Line(createDiv(), {
32+
width: 400,
33+
height: 300,
34+
data: [
35+
{ type: '1', value: 10 },
36+
{ type: '2', value: 3 },
37+
],
38+
xField: 'type',
39+
yField: 'value',
40+
point: {},
41+
});
42+
43+
line.render();
44+
expect(line.chart.geometries[1].elements.length).toBe(2);
45+
46+
line.changeData([...line.options.data, { type: '3', value: 10 }]);
47+
expect(line.chart.geometries[1].elements.length).toBe(3);
48+
49+
line.destroy();
50+
});
51+
});

docs/api/plots/gauge.zh.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ order: 22
4949

5050
| 配置项 | 类型 | 描述 |
5151
| ------ | -------- | ------------------------------------ |
52-
| ticks | number[] | 辅助圆弧显示数字数组 |
53-
| color | string[] | 辅助圆弧的颜色色板,按照色板顺序取值 |
52+
| ticks | _number[]_ | 辅助圆弧显示数字数组 |
53+
| color | _string/|string[]_ | 辅助圆弧的颜色色板,按照色板顺序取值; 当设置 ticks 时,color 无法使用回调的方式 |
54+
55+
<playground rid="gauge" path="progress-plots/gauge/demo/basic.ts"></playground>
5456

5557
#### axis
5658

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Line } from '@antv/g2plot';
2+
3+
fetch('https://gw.alipayobjects.com/os/bmw-prod/1d565782-dde4-4bb6-8946-ea6a38ccf184.json')
4+
.then((res) => res.json())
5+
.then((data) => {
6+
const line = new Line('container', {
7+
data,
8+
padding: 'auto',
9+
xField: 'Date',
10+
yField: 'scales',
11+
xAxis: {
12+
type: 'timeCat',
13+
tickCount: 5,
14+
},
15+
});
16+
17+
line.render();
18+
19+
let year = 2017;
20+
let month = 2;
21+
const interval = setInterval(() => {
22+
if (year > 2211) {
23+
clearInterval(interval);
24+
}
25+
month = (month + 1) % 12;
26+
year += Math.ceil(month / 12);
27+
line.changeData([...line.options.data, { Date: `${year}-${month}`, scales: 1300 * Math.random() + 500 }]);
28+
}, 500);
29+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { G2, Line } from '@antv/g2plot';
2+
3+
G2.registerShape('point', 'breath-point', {
4+
draw(cfg, container) {
5+
const data = cfg.data;
6+
const point = { x: cfg.x, y: cfg.y };
7+
const group = container.addGroup();
8+
if (data.time === '14.20' && data.date === 'today') {
9+
const decorator1 = group.addShape('circle', {
10+
attrs: {
11+
x: point.x,
12+
y: point.y,
13+
r: 10,
14+
fill: cfg.color,
15+
opacity: 0.5,
16+
},
17+
});
18+
const decorator2 = group.addShape('circle', {
19+
attrs: {
20+
x: point.x,
21+
y: point.y,
22+
r: 10,
23+
fill: cfg.color,
24+
opacity: 0.5,
25+
},
26+
});
27+
const decorator3 = group.addShape('circle', {
28+
attrs: {
29+
x: point.x,
30+
y: point.y,
31+
r: 10,
32+
fill: cfg.color,
33+
opacity: 0.5,
34+
},
35+
});
36+
decorator1.animate(
37+
{
38+
r: 20,
39+
opacity: 0,
40+
},
41+
{
42+
duration: 1800,
43+
easing: 'easeLinear',
44+
repeat: true,
45+
}
46+
);
47+
decorator2.animate(
48+
{
49+
r: 20,
50+
opacity: 0,
51+
},
52+
{
53+
duration: 1800,
54+
easing: 'easeLinear',
55+
repeat: true,
56+
delay: 600,
57+
}
58+
);
59+
decorator3.animate(
60+
{
61+
r: 20,
62+
opacity: 0,
63+
},
64+
{
65+
duration: 1800,
66+
easing: 'easeLinear',
67+
repeat: true,
68+
delay: 1200,
69+
}
70+
);
71+
group.addShape('circle', {
72+
attrs: {
73+
x: point.x,
74+
y: point.y,
75+
r: 6,
76+
fill: cfg.color,
77+
opacity: 0.7,
78+
},
79+
});
80+
group.addShape('circle', {
81+
attrs: {
82+
x: point.x,
83+
y: point.y,
84+
r: 1.5,
85+
fill: cfg.color,
86+
},
87+
});
88+
}
89+
90+
return group;
91+
},
92+
});
93+
94+
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/cpu-data.json')
95+
.then((res) => res.json())
96+
.then((data) => {
97+
const plot = new Line('container', {
98+
autoFit: true,
99+
height: 500,
100+
data,
101+
meta: {
102+
cpu: {
103+
time: { type: 'cat' },
104+
max: 100,
105+
min: 0,
106+
},
107+
},
108+
xField: 'time',
109+
yField: 'cpu',
110+
seriesField: 'date',
111+
tooltip: { showMarkers: false },
112+
point: {
113+
shape: 'breath-point',
114+
},
115+
});
116+
117+
plot.render();
118+
});

examples/line/basic/demo/line.ts

-11
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,4 @@ fetch('https://gw.alipayobjects.com/os/bmw-prod/1d565782-dde4-4bb6-8946-ea6a38cc
1515
});
1616

1717
line.render();
18-
let cnt = 0;
19-
let smooth = false;
20-
const interval = setInterval(() => {
21-
if (cnt < 5) {
22-
smooth = !smooth;
23-
cnt += 1;
24-
line.update({ smooth });
25-
} else {
26-
clearInterval(interval);
27-
}
28-
}, 3000);
2918
});

0 commit comments

Comments
 (0)