-
Notifications
You must be signed in to change notification settings - Fork 429
Expand file tree
/
Copy pathIconBadge.tsx
More file actions
125 lines (115 loc) · 2.86 KB
/
Copy pathIconBadge.tsx
File metadata and controls
125 lines (115 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/** @jsxImportSource @antv/infographic-jsx */
import {
ComponentType,
Defs,
Ellipse,
Group,
Text,
} from '@antv/infographic-jsx';
import tinycolor from 'tinycolor2';
import { ItemIcon, ItemLabel } from '../components';
import { getItemProps } from '../utils';
import { registerItem } from './registry';
import type { BaseItemProps } from './types';
export interface IconBadgeProps extends BaseItemProps {
size?: number;
iconSize?: number;
badgeSize?: number;
gap?: number;
}
export const IconBadge: ComponentType<IconBadgeProps> = (props) => {
const [
{
datum,
indexes,
size = 80,
iconSize = 28,
badgeSize = 24,
gap = 8,
themeColors,
width = 84,
height = 105,
},
restProps,
] = getItemProps(props, ['size', 'iconSize', 'badgeSize', 'gap']);
const value = datum.value ?? 0;
const gradientId = `${themeColors.colorPrimary}-icon`;
const badgeGradientId = '#ff6b6b-badge';
return (
<Group {...restProps} width={width} height={height}>
<Defs>
<radialGradient id={gradientId} cx="50%" cy="30%" r="70%">
<stop
offset="0%"
stopColor={tinycolor(themeColors.colorPrimary)
.lighten(30)
.toHexString()}
/>
<stop offset="100%" stopColor={themeColors.colorPrimary} />
</radialGradient>
<linearGradient
id={badgeGradientId}
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" stopColor="#ff6b6b" />
<stop offset="100%" stopColor="#ee5a52" />
</linearGradient>
</Defs>
{/* 主圆形背景 */}
<Ellipse
x={0}
y={0}
width={size}
height={size}
fill={`url(#${gradientId})`}
/>
{/* 图标 */}
<ItemIcon
indexes={indexes}
x={(size - iconSize) / 2}
y={(size - iconSize) / 2}
size={iconSize}
fill={themeColors.colorPrimaryText}
/>
{/* 数值徽章 */}
<Ellipse
x={size - badgeSize + 4}
y={0}
width={badgeSize}
height={badgeSize}
fill={`url(#${badgeGradientId})`}
/>
{/* 徽章数值 */}
<Text
x={size - badgeSize / 2 + 4}
y={badgeSize / 2}
fontSize={10}
fontWeight="bold"
fill={themeColors.colorWhite}
alignHorizontal="center"
alignVertical="center"
>
{value > 99 ? '99+' : Math.round(value)}
</Text>
{/* 标签 */}
<ItemLabel
indexes={indexes}
x={0}
y={size + gap}
width={size}
alignHorizontal="center"
fontSize={12}
fill={themeColors.colorText}
>
{datum.label}
</ItemLabel>
</Group>
);
};
registerItem('icon-badge', {
component: IconBadge,
composites: ['icon', 'label'],
});