Skip to content

Commit 7a34182

Browse files
authored
feat(gauge): 仪表盘支持配置 style,支持圆角仪表盘 (#2395)
* feat(gauge): 仪表盘支持配置 style,支持圆角仪表盘 * feat(gauge): 仪表盘生成辅助 range, 携带原始数值 百分比 增加 style 回调单测 增加文档 * fix: 移除wu无用变量,处理 lint
1 parent b8e99f2 commit 7a34182

File tree

7 files changed

+134
-22
lines changed

7 files changed

+134
-22
lines changed
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Gauge } from '../../../../src';
2+
import { createDiv } from '../../../utils/dom';
3+
4+
describe('gauge', () => {
5+
const gauge = new Gauge(createDiv(), {
6+
width: 600,
7+
height: 300,
8+
autoFit: false,
9+
percent: 0.75,
10+
range: {
11+
ticks: [0, 0.2, 0.4, 0.75, 1],
12+
color: ['red', 'yellow', 'green'],
13+
},
14+
indicator: {},
15+
gaugeStyle: {
16+
lineCap: 'round',
17+
lineWidth: 2,
18+
stroke: 'red',
19+
},
20+
});
21+
22+
gauge.render();
23+
24+
it('gaugeStyle', async () => {
25+
const [, v2] = gauge.chart.views;
26+
expect(v2.geometries[0].type).toBe('interval');
27+
// v2 gaugeStyle 生效
28+
expect(v2.geometries[0].elements[0].shape.attr('lineCap')).toBe('round');
29+
expect(v2.geometries[0].elements[0].shape.attr('lineWidth')).toBe(2);
30+
expect(v2.geometries[0].elements[0].shape.attr('stroke')).toBe('red');
31+
});
32+
33+
it('gaugeStyle, with callback', () => {
34+
gauge.update({
35+
percent: 0.9,
36+
gaugeStyle: ({ percent }) => {
37+
return {
38+
lineCap: 'round',
39+
lineWidth: 2,
40+
stroke: percent > 0.8 ? 'green' : 'red',
41+
};
42+
},
43+
});
44+
45+
const [, v2] = gauge.chart.views;
46+
expect(v2.geometries[0].type).toBe('interval');
47+
// v2 gaugeStyle 生效
48+
expect(v2.geometries[0].elements[0].shape.attr('lineCap')).toBe('round');
49+
expect(v2.geometries[0].elements[0].shape.attr('lineWidth')).toBe(2);
50+
expect(v2.geometries[0].elements[0].shape.attr('stroke')).toBe('green');
51+
});
52+
53+
afterAll(() => {
54+
gauge.destroy();
55+
});
56+
});

docs/api/plots/gauge.en.md

+10
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ It works when `type = 'meter'`. Properties are as followed:
7373

7474
<img src="https://gw.alipayobjects.com/zos/antfincdn/WBhwhNUzkg/image.png" width="400" align="center" style="display:flex;margin:0 auto;" alt="gauge">
7575

76+
#### gaugeStyle
77+
78+
<description>**optional** _StyleAttr | Function_</description>
79+
80+
Gauge graphic style.
81+
82+
`markdown:docs/common/shape-style.en.md`
83+
84+
### Plot Components
85+
7686
#### axis
7787

7888
<description>**optional** _object_</description>

docs/api/plots/gauge.zh.md

+8
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ order: 5
7272

7373
<img src="https://gw.alipayobjects.com/zos/antfincdn/WBhwhNUzkg/image.png" width="400" align="center" style="display:flex;margin:0 auto;" alt="gauge">
7474

75+
#### gaugeStyle
76+
77+
<description>**optional** _StyleAttr | Function_</description>
78+
79+
仪表盘的样式设置。
80+
81+
`markdown:docs/common/shape-style.zh.md`
82+
7583
### 图表组件
7684

7785
#### axis

src/plots/gauge/adaptor.ts

+24-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { isString } from '@antv/util';
22
import { interaction, animation, theme, scale, annotation } from '../../adaptor/common';
3+
import { interval } from '../../adaptor/geometries';
34
import { AXIS_META_CONFIG_KEYS } from '../../constant';
45
import { Params } from '../../core/adaptor';
5-
import { Data } from '../../types';
66
import { deepAssign, flow, pick, renderGaugeStatistic } from '../../utils';
77
import {
88
RANGE_TYPE,
@@ -13,7 +13,7 @@ import {
1313
RANGE_VIEW_ID,
1414
MASK_VIEW_ID,
1515
} from './constants';
16-
import { GaugeOptions } from './types';
16+
import { GaugeCustomInfo, GaugeOptions } from './types';
1717
import { getIndicatorData, getRangeData } from './utils';
1818

1919
/**
@@ -22,7 +22,7 @@ import { getIndicatorData, getRangeData } from './utils';
2222
*/
2323
function geometry(params: Params<GaugeOptions>): Params<GaugeOptions> {
2424
const { chart, options } = params;
25-
const { percent, range, radius, innerRadius, startAngle, endAngle, axis, indicator } = options;
25+
const { percent, range, radius, innerRadius, startAngle, endAngle, axis, indicator, gaugeStyle } = options;
2626
const { color } = range;
2727

2828
// 指标 & 指针
@@ -54,14 +54,30 @@ function geometry(params: Params<GaugeOptions>): Params<GaugeOptions> {
5454
}
5555

5656
// 辅助 range
57-
// [{ range: 1, type: '0' }]
58-
const rangeData: Data = getRangeData(percent, options.range);
57+
// [{ range: 1, type: '0', percent: 原始进度百分比 }]
58+
const rangeData = getRangeData(percent, options.range);
5959
const v2 = chart.createView({ id: RANGE_VIEW_ID });
6060
v2.data(rangeData);
6161

6262
const rangeColor = isString(color) ? [color, DEFAULT_COLOR] : color;
6363

64-
v2.interval().position(`1*${RANGE_VALUE}`).color(RANGE_TYPE, rangeColor).adjust('stack');
64+
interval({
65+
chart: v2,
66+
options: {
67+
xField: '1',
68+
yField: RANGE_VALUE,
69+
seriesField: RANGE_TYPE,
70+
rawFields: [PERCENT],
71+
isStack: true,
72+
interval: {
73+
color: rangeColor,
74+
style: gaugeStyle,
75+
},
76+
args: {
77+
zIndexReversed: true,
78+
},
79+
},
80+
});
6581

6682
v2.coordinate('polar', {
6783
innerRadius,
@@ -93,12 +109,8 @@ function meterView(params: Params<GaugeOptions>): Params<GaugeOptions> {
93109

94110
const v3 = chart.createView({ id: MASK_VIEW_ID });
95111
v3.data([{ [RANGE_TYPE]: '1', [RANGE_VALUE]: 1 }]);
96-
v3.interval()
97-
.position(`1*${RANGE_VALUE}`)
98-
.color(color)
99-
.adjust('stack')
100-
.shape('meter-gauge')
101-
.customInfo(meter || {});
112+
const customInfo: GaugeCustomInfo = { meter };
113+
v3.interval().position(`1*${RANGE_VALUE}`).color(color).adjust('stack').shape('meter-gauge').customInfo(customInfo);
102114
v3.coordinate('polar', { innerRadius, radius, startAngle, endAngle }).transpose();
103115
}
104116

src/plots/gauge/shapes/meter-gauge.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { registerShape, Types, Util } from '@antv/g2';
2-
import { getSectorPath } from '@antv/g2/lib/util/graphics';
2+
import { GaugeCustomInfo } from '../types';
3+
4+
type ShapeCfg = Omit<Types.ShapeInfo, 'customInfo'> & {
5+
customInfo: GaugeCustomInfo;
6+
};
37

48
// 自定义Shape 部分
59
registerShape('interval', 'meter-gauge', {
6-
draw(cfg: Types.ShapeInfo, container) {
10+
draw(cfg: ShapeCfg, container) {
711
// 使用 customInfo 传递参数
8-
const { steps: STEP = 50, stepRatio = 0.5 } = cfg.customInfo;
12+
const { meter = {} } = cfg.customInfo;
13+
const { steps: STEP = 50, stepRatio = 0.5 } = meter;
914

1015
const total = this.coordinate.endAngle - this.coordinate.startAngle;
1116
let interval = total / STEP;
@@ -30,7 +35,7 @@ registerShape('interval', 'meter-gauge', {
3035
for (let i = startAngle, j = 0; i < endAngle && j < 2 * STEP - 1; j++) {
3136
const drawn = j % 2;
3237
if (drawn) {
33-
const path = getSectorPath(
38+
const path = Util.getSectorPath(
3439
center.x,
3540
center.y,
3641
radius,

src/plots/gauge/types.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { Options, ShapeStyle, Statistic } from '../../types';
1+
import { Options, ShapeStyle, Statistic, StyleAttr } from '../../types';
22
import { Axis } from '../../types/axis';
3+
import { PERCENT, RANGE_TYPE, RANGE_VALUE } from './constants';
34

45
/** 指标指标的配置 */
56
export type Indicator = {
@@ -20,6 +21,15 @@ type Range = {
2021
readonly color?: string | string[];
2122
};
2223

24+
/**
25+
* 仪表盘辅助生成的 rangeData
26+
*/
27+
export type GaugeRangeData = {
28+
readonly [RANGE_VALUE]?: number;
29+
readonly [RANGE_TYPE]: string;
30+
readonly [PERCENT]: number;
31+
}[];
32+
2333
/** 仪表盘配置类型定义 */
2434
export interface GaugeOptions
2535
extends Omit<Options, 'data' | 'tooltip' | 'legend' | 'xAxis' | 'yAxis' | 'xField' | 'yField' | 'color'> {
@@ -41,6 +51,8 @@ export interface GaugeOptions
4151
readonly indicator?: false | Indicator;
4252
/** 统计文本 */
4353
readonly statistic?: Statistic;
54+
/** 仪表盘样式 */
55+
readonly gaugeStyle?: StyleAttr;
4456

4557
// meter gauge 相关配置
4658
/** 仪表盘类型, 可选项: 'meter', default 为空 */
@@ -53,3 +65,11 @@ export interface GaugeOptions
5365
readonly stepRatio?: number;
5466
};
5567
}
68+
69+
/**
70+
* 仪表盘 自定义 shape 使用的 customInfo
71+
*/
72+
export type GaugeCustomInfo = {
73+
/** 仪表盘 meter 类型的相关配置 */
74+
readonly meter?: GaugeOptions['meter'];
75+
};

src/plots/gauge/utils.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { clamp, get, size } from '@antv/util';
22
import { Data, Datum } from '../../types';
33
import { RANGE_VALUE, RANGE_TYPE, PERCENT } from './constants';
4-
import { GaugeOptions } from './types';
4+
import { GaugeOptions, GaugeRangeData } from './types';
55

66
/**
77
* 将 range 生成为 data 数据
88
* @param range
99
* @param key
10+
* @returns {GaugeRangeData}
1011
*/
11-
export function processRangeData(range: number[]): Data {
12+
export function processRangeData(range: number[], percent: GaugeOptions['percent']): GaugeRangeData {
1213
return (
1314
range
1415
// 映射为 stack 的数据
1516
.map((r: number, idx: number) => {
16-
return { [RANGE_VALUE]: r - (range[idx - 1] || 0), [RANGE_TYPE]: `${idx}` };
17+
return { [RANGE_VALUE]: r - (range[idx - 1] || 0), [RANGE_TYPE]: `${idx}`, [PERCENT]: percent };
1718
})
1819
// 去掉 0 的数据
1920
.filter((d: Datum) => !!d[RANGE_VALUE])
@@ -33,9 +34,9 @@ export function getIndicatorData(percent: GaugeOptions['percent']): Data {
3334
* @param percent
3435
* @param range
3536
*/
36-
export function getRangeData(percent: GaugeOptions['percent'], range?: GaugeOptions['range']): Data {
37+
export function getRangeData(percent: GaugeOptions['percent'], range?: GaugeOptions['range']): GaugeRangeData {
3738
const ticks = get(range, ['ticks'], []);
3839

3940
const clampTicks = size(ticks) ? ticks : [0, clamp(percent, 0, 1), 1];
40-
return processRangeData(clampTicks as number[]);
41+
return processRangeData(clampTicks as number[], percent);
4142
}

0 commit comments

Comments
 (0)