diff --git a/__tests__/unit/plots/gauge/style-spec.ts b/__tests__/unit/plots/gauge/style-spec.ts
new file mode 100644
index 0000000000..392fce18cf
--- /dev/null
+++ b/__tests__/unit/plots/gauge/style-spec.ts
@@ -0,0 +1,56 @@
+import { Gauge } from '../../../../src';
+import { createDiv } from '../../../utils/dom';
+
+describe('gauge', () => {
+ const gauge = new Gauge(createDiv(), {
+ width: 600,
+ height: 300,
+ autoFit: false,
+ percent: 0.75,
+ range: {
+ ticks: [0, 0.2, 0.4, 0.75, 1],
+ color: ['red', 'yellow', 'green'],
+ },
+ indicator: {},
+ gaugeStyle: {
+ lineCap: 'round',
+ lineWidth: 2,
+ stroke: 'red',
+ },
+ });
+
+ gauge.render();
+
+ it('gaugeStyle', async () => {
+ const [, v2] = gauge.chart.views;
+ expect(v2.geometries[0].type).toBe('interval');
+ // v2 gaugeStyle 生效
+ expect(v2.geometries[0].elements[0].shape.attr('lineCap')).toBe('round');
+ expect(v2.geometries[0].elements[0].shape.attr('lineWidth')).toBe(2);
+ expect(v2.geometries[0].elements[0].shape.attr('stroke')).toBe('red');
+ });
+
+ it('gaugeStyle, with callback', () => {
+ gauge.update({
+ percent: 0.9,
+ gaugeStyle: ({ percent }) => {
+ return {
+ lineCap: 'round',
+ lineWidth: 2,
+ stroke: percent > 0.8 ? 'green' : 'red',
+ };
+ },
+ });
+
+ const [, v2] = gauge.chart.views;
+ expect(v2.geometries[0].type).toBe('interval');
+ // v2 gaugeStyle 生效
+ expect(v2.geometries[0].elements[0].shape.attr('lineCap')).toBe('round');
+ expect(v2.geometries[0].elements[0].shape.attr('lineWidth')).toBe(2);
+ expect(v2.geometries[0].elements[0].shape.attr('stroke')).toBe('green');
+ });
+
+ afterAll(() => {
+ gauge.destroy();
+ });
+});
diff --git a/docs/api/plots/gauge.en.md b/docs/api/plots/gauge.en.md
index ea0026fb51..91da6bc78b 100644
--- a/docs/api/plots/gauge.en.md
+++ b/docs/api/plots/gauge.en.md
@@ -73,6 +73,16 @@ It works when `type = 'meter'`. Properties are as followed:
+#### gaugeStyle
+
+**optional** _StyleAttr | Function_
+
+Gauge graphic style.
+
+`markdown:docs/common/shape-style.en.md`
+
+### Plot Components
+
#### axis
**optional** _object_
diff --git a/docs/api/plots/gauge.zh.md b/docs/api/plots/gauge.zh.md
index 74172a6bc6..d3c47e6928 100644
--- a/docs/api/plots/gauge.zh.md
+++ b/docs/api/plots/gauge.zh.md
@@ -72,6 +72,14 @@ order: 5
+#### gaugeStyle
+
+**optional** _StyleAttr | Function_
+
+仪表盘的样式设置。
+
+`markdown:docs/common/shape-style.zh.md`
+
### 图表组件
#### axis
diff --git a/src/plots/gauge/adaptor.ts b/src/plots/gauge/adaptor.ts
index 0129ccb014..9edfc06751 100644
--- a/src/plots/gauge/adaptor.ts
+++ b/src/plots/gauge/adaptor.ts
@@ -1,8 +1,8 @@
import { isString } from '@antv/util';
import { interaction, animation, theme, scale, annotation } from '../../adaptor/common';
+import { interval } from '../../adaptor/geometries';
import { AXIS_META_CONFIG_KEYS } from '../../constant';
import { Params } from '../../core/adaptor';
-import { Data } from '../../types';
import { deepAssign, flow, pick, renderGaugeStatistic } from '../../utils';
import {
RANGE_TYPE,
@@ -13,7 +13,7 @@ import {
RANGE_VIEW_ID,
MASK_VIEW_ID,
} from './constants';
-import { GaugeOptions } from './types';
+import { GaugeCustomInfo, GaugeOptions } from './types';
import { getIndicatorData, getRangeData } from './utils';
/**
@@ -22,7 +22,7 @@ import { getIndicatorData, getRangeData } from './utils';
*/
function geometry(params: Params): Params {
const { chart, options } = params;
- const { percent, range, radius, innerRadius, startAngle, endAngle, axis, indicator } = options;
+ const { percent, range, radius, innerRadius, startAngle, endAngle, axis, indicator, gaugeStyle } = options;
const { color } = range;
// 指标 & 指针
@@ -54,14 +54,30 @@ function geometry(params: Params): Params {
}
// 辅助 range
- // [{ range: 1, type: '0' }]
- const rangeData: Data = getRangeData(percent, options.range);
+ // [{ range: 1, type: '0', percent: 原始进度百分比 }]
+ const rangeData = getRangeData(percent, options.range);
const v2 = chart.createView({ id: RANGE_VIEW_ID });
v2.data(rangeData);
const rangeColor = isString(color) ? [color, DEFAULT_COLOR] : color;
- v2.interval().position(`1*${RANGE_VALUE}`).color(RANGE_TYPE, rangeColor).adjust('stack');
+ interval({
+ chart: v2,
+ options: {
+ xField: '1',
+ yField: RANGE_VALUE,
+ seriesField: RANGE_TYPE,
+ rawFields: [PERCENT],
+ isStack: true,
+ interval: {
+ color: rangeColor,
+ style: gaugeStyle,
+ },
+ args: {
+ zIndexReversed: true,
+ },
+ },
+ });
v2.coordinate('polar', {
innerRadius,
@@ -93,12 +109,8 @@ function meterView(params: Params): Params {
const v3 = chart.createView({ id: MASK_VIEW_ID });
v3.data([{ [RANGE_TYPE]: '1', [RANGE_VALUE]: 1 }]);
- v3.interval()
- .position(`1*${RANGE_VALUE}`)
- .color(color)
- .adjust('stack')
- .shape('meter-gauge')
- .customInfo(meter || {});
+ const customInfo: GaugeCustomInfo = { meter };
+ v3.interval().position(`1*${RANGE_VALUE}`).color(color).adjust('stack').shape('meter-gauge').customInfo(customInfo);
v3.coordinate('polar', { innerRadius, radius, startAngle, endAngle }).transpose();
}
diff --git a/src/plots/gauge/shapes/meter-gauge.ts b/src/plots/gauge/shapes/meter-gauge.ts
index a0c641e550..db1dab0877 100644
--- a/src/plots/gauge/shapes/meter-gauge.ts
+++ b/src/plots/gauge/shapes/meter-gauge.ts
@@ -1,11 +1,16 @@
import { registerShape, Types, Util } from '@antv/g2';
-import { getSectorPath } from '@antv/g2/lib/util/graphics';
+import { GaugeCustomInfo } from '../types';
+
+type ShapeCfg = Omit & {
+ customInfo: GaugeCustomInfo;
+};
// 自定义Shape 部分
registerShape('interval', 'meter-gauge', {
- draw(cfg: Types.ShapeInfo, container) {
+ draw(cfg: ShapeCfg, container) {
// 使用 customInfo 传递参数
- const { steps: STEP = 50, stepRatio = 0.5 } = cfg.customInfo;
+ const { meter = {} } = cfg.customInfo;
+ const { steps: STEP = 50, stepRatio = 0.5 } = meter;
const total = this.coordinate.endAngle - this.coordinate.startAngle;
let interval = total / STEP;
@@ -30,7 +35,7 @@ registerShape('interval', 'meter-gauge', {
for (let i = startAngle, j = 0; i < endAngle && j < 2 * STEP - 1; j++) {
const drawn = j % 2;
if (drawn) {
- const path = getSectorPath(
+ const path = Util.getSectorPath(
center.x,
center.y,
radius,
diff --git a/src/plots/gauge/types.ts b/src/plots/gauge/types.ts
index fc84a77e5f..420f9d3ec9 100644
--- a/src/plots/gauge/types.ts
+++ b/src/plots/gauge/types.ts
@@ -1,5 +1,6 @@
-import { Options, ShapeStyle, Statistic } from '../../types';
+import { Options, ShapeStyle, Statistic, StyleAttr } from '../../types';
import { Axis } from '../../types/axis';
+import { PERCENT, RANGE_TYPE, RANGE_VALUE } from './constants';
/** 指标指标的配置 */
export type Indicator = {
@@ -20,6 +21,15 @@ type Range = {
readonly color?: string | string[];
};
+/**
+ * 仪表盘辅助生成的 rangeData
+ */
+export type GaugeRangeData = {
+ readonly [RANGE_VALUE]?: number;
+ readonly [RANGE_TYPE]: string;
+ readonly [PERCENT]: number;
+}[];
+
/** 仪表盘配置类型定义 */
export interface GaugeOptions
extends Omit {
@@ -41,6 +51,8 @@ export interface GaugeOptions
readonly indicator?: false | Indicator;
/** 统计文本 */
readonly statistic?: Statistic;
+ /** 仪表盘样式 */
+ readonly gaugeStyle?: StyleAttr;
// meter gauge 相关配置
/** 仪表盘类型, 可选项: 'meter', default 为空 */
@@ -53,3 +65,11 @@ export interface GaugeOptions
readonly stepRatio?: number;
};
}
+
+/**
+ * 仪表盘 自定义 shape 使用的 customInfo
+ */
+export type GaugeCustomInfo = {
+ /** 仪表盘 meter 类型的相关配置 */
+ readonly meter?: GaugeOptions['meter'];
+};
diff --git a/src/plots/gauge/utils.ts b/src/plots/gauge/utils.ts
index fc2d7854b8..e028e3c4bd 100644
--- a/src/plots/gauge/utils.ts
+++ b/src/plots/gauge/utils.ts
@@ -1,19 +1,20 @@
import { clamp, get, size } from '@antv/util';
import { Data, Datum } from '../../types';
import { RANGE_VALUE, RANGE_TYPE, PERCENT } from './constants';
-import { GaugeOptions } from './types';
+import { GaugeOptions, GaugeRangeData } from './types';
/**
* 将 range 生成为 data 数据
* @param range
* @param key
+ * @returns {GaugeRangeData}
*/
-export function processRangeData(range: number[]): Data {
+export function processRangeData(range: number[], percent: GaugeOptions['percent']): GaugeRangeData {
return (
range
// 映射为 stack 的数据
.map((r: number, idx: number) => {
- return { [RANGE_VALUE]: r - (range[idx - 1] || 0), [RANGE_TYPE]: `${idx}` };
+ return { [RANGE_VALUE]: r - (range[idx - 1] || 0), [RANGE_TYPE]: `${idx}`, [PERCENT]: percent };
})
// 去掉 0 的数据
.filter((d: Datum) => !!d[RANGE_VALUE])
@@ -33,9 +34,9 @@ export function getIndicatorData(percent: GaugeOptions['percent']): Data {
* @param percent
* @param range
*/
-export function getRangeData(percent: GaugeOptions['percent'], range?: GaugeOptions['range']): Data {
+export function getRangeData(percent: GaugeOptions['percent'], range?: GaugeOptions['range']): GaugeRangeData {
const ticks = get(range, ['ticks'], []);
const clampTicks = size(ticks) ? ticks : [0, clamp(percent, 0, 1), 1];
- return processRangeData(clampTicks as number[]);
+ return processRangeData(clampTicks as number[], percent);
}