Skip to content

Commit

Permalink
feat: add radial-bar (#2189)
Browse files Browse the repository at this point in the history
* feat: add radial-bar

* feat: 新增健身数据

* feat(radial-bar): change type name

* feat(radial-bar): add startAngle

* feat(radial-bar): add background and line

---------

Co-authored-by: shengzheng <huangshengpu.hsp@digital-engine.com>
Co-authored-by: Joel Alan <31396322+lxfu1@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 20, 2023
1 parent a36c807 commit a6f2571
Show file tree
Hide file tree
Showing 17 changed files with 712 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/plots/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Gauge from './gauge';
import Liquid from './liquid';
import WordCloud from './wordCloud';
import Treemap from './treemap';
import RadialBar from './radial-bar';
import CirclePacking from './circlePacking';
import Violin from './violin';
import BidirectionalBar from './bidirectional-bar';
Expand Down Expand Up @@ -76,6 +77,7 @@ export {
Liquid,
WordCloud,
Treemap,
RadialBar,
CirclePacking,
Violin,
BidirectionalBar,
Expand Down
10 changes: 10 additions & 0 deletions packages/plots/src/components/radial-bar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { RadialBarOptions } from '../../core';
import { CommonConfig } from '../../interface';
import { BaseChart } from '../base';

export type RadialBarConfig = CommonConfig<RadialBarOptions>;

const RadialBar = (props: RadialBarConfig) => <BaseChart {...props} chartType="RadialBar" />;

export default RadialBar;
3 changes: 3 additions & 0 deletions packages/plots/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type { GaugeOptions } from './plots/gauge';
export type { LiquidOptions } from './plots/liquid';
export type { WordCloudOptions } from './plots/wordCloud';
export type { TreemapOptions } from './plots/treemap';
export type { RadialBarOptions } from './plots/radial-bar';
export type { CirclePackingOptions } from './plots/circlePacking';
export type { ViolinOptions } from './plots/violin';
export type { BidirectionalBarOptions } from './plots/bidirectional-bar';
Expand Down Expand Up @@ -57,6 +58,7 @@ import { Gauge } from './plots/gauge';
import { Liquid } from './plots/liquid';
import { WordCloud } from './plots/wordCloud';
import { Treemap } from './plots/treemap';
import { RadialBar } from './plots/radial-bar';
import { CirclePacking } from './plots/circlePacking';
import { Violin } from './plots/violin';
import { BidirectionalBar } from './plots/bidirectional-bar';
Expand Down Expand Up @@ -89,6 +91,7 @@ export const Plots = {
Liquid,
WordCloud,
Treemap,
RadialBar,
CirclePacking,
Violin,
BidirectionalBar,
Expand Down
88 changes: 88 additions & 0 deletions packages/plots/src/core/plots/radial-bar/adaptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { flow, set, pick, transformOptions, isNumber, get } from '../../utils';
import { COORDIANTE_OPTIONS, mark } from '../../components';
import type { Adaptor } from '../../types';
import type { RadialBarOptions } from './type';

type Params = Adaptor<RadialBarOptions>;

/**
* @param chart
* @param options
*/
export function adaptor(params: Params) {
/**
* coordinate 配置
* @param params
*/
const coordinate = (params: Params) => {
const { options } = params;
const { startAngle, maxAngle, coordinate, radius, innerRadius } = options;
// 默认开始角度是-90度
const start = isNumber(startAngle) ? (startAngle / (2 * Math.PI)) * 360 : -90;
// 结束角度通过maxAngle来计算
const end = isNumber(maxAngle) ? ((Number(maxAngle) + start) / 180) * Math.PI : Math.PI;
set(params, ['options', 'coordinate'], {
...coordinate,
...pick(options.coordinate, COORDIANTE_OPTIONS),
endAngle: end,
outerRadius: radius,
innerRadius,
startAngle: startAngle ?? -Math.PI / 2,
});

return params;
};

/**
* tooltip 配置
* @param params
*/
const tooltip = (params) => {
const { options } = params;
const { tooltip, xField, yField } = options;
if (!tooltip) {
set(options, 'tooltip', {
title: false,
items: [
(d) => {
return { name: d[xField], value: d[yField] };
},
],
});
}
return params;
};

/**
* background 配置
* @param params
*/
const background = (params) => {
const { options } = params;
const { markBackground, children, scale, coordinate, xField } = options;
const domain = get(scale, 'y.domain', []);
if (markBackground) {
children.unshift({
type: 'interval',
xField: xField,
yField: domain[domain.length - 1],
colorField: markBackground.color,
scale: { color: { type: 'identity' } },
style: {
fillOpacity: markBackground.opacity,
fill: markBackground.color ? undefined : '#e0e4ee', // 默认用fill填满灰色背景
},
// 背景图需要填满整个圆
coordinate: {
...coordinate,
startAngle: -Math.PI / 2,
endAngle: (3 / 2) * Math.PI,
},
animate: false,
});
}
return params;
};

return flow(coordinate, tooltip, background, transformOptions, mark)(params);
}
51 changes: 51 additions & 0 deletions packages/plots/src/core/plots/radial-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Plot } from '../../base';
import type { Adaptor } from '../../types';
import { adaptor } from './adaptor';
import { RadialBarOptions } from './type';

export type { RadialBarOptions };

export class RadialBar extends Plot<RadialBarOptions> {
/** 图表类型 */
public type = 'radial';

/**
* 获取 玉珏图 默认配置项
* 供外部使用
*/
static getDefaultOptions(): Partial<RadialBarOptions> {
return {
type: 'view',
children: [{ type: 'interval' }],
coordinate: { type: 'radial', innerRadius: 0.1, outerRadius: 1, endAngle: Math.PI },
animate: { enter: { type: 'waveIn', duration: 800 } },
axis: {
y: {
nice: true,
labelAutoHide: true,
labelAutoRotate: false,
},
x: {
title: false,
nice: true,
labelAutoRotate: false,
labelAutoHide: { type: 'equidistance', cfg: { minGap: 6 } },
},
},
};
}

/**
* 获取 玉珏图 默认配置
*/
protected getDefaultOptions() {
return RadialBar.getDefaultOptions();
}

/**
* 玉珏图适配器
*/
protected getSchemaAdaptor(): (params: Adaptor<RadialBarOptions>) => void {
return adaptor;
}
}
3 changes: 3 additions & 0 deletions packages/plots/src/core/plots/radial-bar/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { BaseOptions, Options } from '../../types/common';

export type RadialBarOptions = Options & BaseOptions;
59 changes: 59 additions & 0 deletions site/examples/statistics/radial-bar/demo/apple-watch-activity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { RadialBar } from '@ant-design/plots';
import React from 'react';
import ReactDOM from 'react-dom';

const data = [
{
name: 'activity1',
percent: 2370,
color: '#1ad5de',
icon: 'https://gw.alipayobjects.com/zos/antfincdn/ck11Y6aRrz/shangjiantou.png',
},
{
name: 'activity2',
percent: 800,
color: '#a0ff03',
icon: 'https://gw.alipayobjects.com/zos/antfincdn/zY2JB7hhrO/shuangjiantou.png',
},
{
name: 'activity3',
percent: 650,
color: '#e90b3a',
icon: 'https://gw.alipayobjects.com/zos/antfincdn/%24qBxSxdK05/jiantou.png',
},
];

const DemoRadialBar = () => {
const config = {
data,
xField: 'name',
yField: 'percent',
width: 400,
height: 244,
autoFit: false,
appendPadding: [50, 0, 50, 0],
// maxAngle: 90, //最大旋转角度,
radius: 1,
innerRadius: 0.2,
style: {
radius: 26, // 圆角
},
theme: 'dark',
colorField: 'name',
colorKey: 'color',
legend: false,
axis: { x: false, y: false },
markBackground: {
opacity: 0.25,
color: 'color',
},
scale: {
y: {
domain: [0, 12000], // 设定范围用于背景图的渲染获取最大值
},
},
};
return <RadialBar {...config} />;
};

ReactDOM.render(<DemoRadialBar />, document.getElementById('container'));
54 changes: 54 additions & 0 deletions site/examples/statistics/radial-bar/demo/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { RadialBar } from '@ant-design/plots';
import React from 'react';
import ReactDOM from 'react-dom';

const data = [
{ name: 'X6', star: 297 },
{ name: 'G', star: 506 },
{ name: 'AVA', star: 805 },
{ name: 'G2Plot', star: 1478 },
{ name: 'L7', star: 2029 },
{ name: 'G6', star: 7100 },
{ name: 'F2', star: 7346 },
{ name: 'G2', star: 10178 },
];

const DemoRadialBar = () => {
const config = {
data,
xField: 'name',
yField: 'star',
maxAngle: 350,
radius: 1,
innerRadius: 0.2,
tooltip: {
items: ['star'],
},
legend:false,
axis: {
y: false,
},
markBackground: {
opacity: 0.25,
},
scale:{
y: {
domain: [0, 12000], // 设定范围用于背景图的渲染获取最大值
},
},
style: {
radius: 180,
fill: ({ star }) => {
if (star > 10000) {
return '#6349ec';
} else if (star > 1000) {
return '#ff9300';
}
return '#ff93a7';
},
},
};
return <RadialBar {...config} />;
};

ReactDOM.render(<DemoRadialBar />, document.getElementById('container'));
32 changes: 32 additions & 0 deletions site/examples/statistics/radial-bar/demo/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { RadialBar } from '@ant-design/plots';
import React from 'react';
import ReactDOM from 'react-dom';


const data = [
{ name: 'X6', star: 297 },
{ name: 'G', star: 506 },
{ name: 'AVA', star: 805 },
{ name: 'G2Plot', star: 1478 },
{ name: 'L7', star: 2029 },
{ name: 'G6', star: 7100 },
{ name: 'F2', star: 7346 },
{ name: 'G2', star: 10178 },
];

const DemoRadialBar = () => {
const config = {
data,
xField: 'name',
yField: 'star',
// maxAngle: 90, //最大旋转角度,
radius: 1,
innerRadius: 0.2,
tooltip: {
items:['star']
},
};
return <RadialBar {...config} />;
};

ReactDOM.render(<DemoRadialBar />, document.getElementById('container'));
42 changes: 42 additions & 0 deletions site/examples/statistics/radial-bar/demo/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { RadialBar } from '@ant-design/plots';
import React from 'react';
import ReactDOM from 'react-dom';

const data = [
{ name: 'X6', star: 297 },
{ name: 'G', star: 506 },
{ name: 'AVA', star: 805 },
{ name: 'G2Plot', star: 1478 },
{ name: 'L7', star: 2029 },
{ name: 'G6', star: 7100 },
{ name: 'F2', star: 7346 },
{ name: 'G2', star: 10178 },
];

const DemoRadialBar = () => {
const config = {
data,
xField: 'name',
yField: 'star',
maxAngle: 270,
radius: 0.8,
innerRadius: 0.2,
tooltip: {
items: ['star'],
},
// colorField: 'star', // 会默认给颜色
style: {
fill: ({ star }) => {
if (star > 10000) {
return '#36c361';
} else if (star > 1000) {
return '#2194ff';
}
return '#ff4d4f';
},
},
};
return <RadialBar {...config} />;
};

ReactDOM.render(<DemoRadialBar />, document.getElementById('container'));
Loading

0 comments on commit a6f2571

Please sign in to comment.