1- @inject IJSRuntime JsRuntime
2-
3- <div style =" display : flex ; justify-content : center ;" >
4- <div style =" display : inline " >
5- <div style =" position : relative ; max-width : @(Width)px " >
6- <div class =" user-avatar-border" >
7- <div class =" hexagon-progress" style =" width : @(Width)px ; height : @(Height)px ; position : relative ;" ></div >
8- </div >
9-
10- <div class =" user-avatar-content"
11- style =" position : absolute ;
12- top : @(Width * 0.16 )px ;
13- left : @(Height * 0.17 )px ; " >
14- <div class =" hexagon-image"
15- style =" width : @(Width * 0.683 )px ;
16- height : @(Height * 0.683 );
17- position : relative ; " >
18- @CenterContent
19- </div >
20- </div >
21-
22- <div class =" user-avatar-badge" style =" display : flex ;
23- flex-wrap : wrap ;
24- align-items : center ;
25- justify-content : center ;
26- position : absolute ;
27- bottom : 25px ;
28- right : -3px ; " >
29-
30- <div class =" user-avatar-badge-border" style ="
31- display : inline-block ;
32- position : absolute ;
33- z-index : 1 " >
34- <div class =" hexagon-avatar-badge"
35- style =" width : 32px ; height : 36px ; position : absolute ;" ></div >
36- </div >
37-
38- <div class =" user-avatar-badge-content"
39- style ="
40- display : inline-block ;
41- z-index : 5 ;
42- position : absolute ; " >
43- <div class =" hexagon-dark" style =" width : 26px ;
44- height : 28px ;
45- position : relative ; " ></div >
46- </div >
47- <p class =" user-avatar-badge-text" style ="
48- position : absolute ;
49- pointer-events : none ;
50- z-index : 6 ;
51- display : inline-block ;
52- font-weight : 700 ; " >
53- @UserLevel
54- </p >
55- </div >
56- </div >
1+ @using System .Globalization
2+
3+ <div class =" hex-progress-bar-container" style =" width : @(Size + " px " ); height: @(Size + " px " );" >
4+ <svg viewBox =" 0 0 @Size @Size" class =" hex-progress-bar-svg" >
5+ @* Background Hexagon (optional for visual clarity when not filled)*@
6+ <polygon points =" @HexagonPoints"
7+ fill =" none"
8+ stroke =" @BackgroundColor"
9+ stroke-width =" @StrokeWidth"
10+ stroke-linejoin =" round"
11+ stroke-linecap =" round" />
12+
13+ @* Progress Hexagon*@
14+ <polygon points =" @HexagonPoints"
15+ fill =" none"
16+ stroke =" @ProgressColor"
17+ stroke-width =" @StrokeWidth"
18+ stroke-linecap =" round"
19+ stroke-linejoin =" round"
20+ stroke-dasharray =" @StrokeDashArray"
21+ stroke-dashoffset =" @StrokeDashOffset"
22+ transform =" rotate(-90 @HexCenterX @HexCenterY)" /> @* Rotate to start at the top*@
23+ </svg >
24+
25+ <div class =" hex-content-center" >
26+ @ChildContent
5727 </div >
5828</div >
59- @code {
60-
61- [Parameter ]
62- public string ImageUrl { get ; set ; } = string .Empty ;
63-
64- [Parameter ]
65- public int UserLevel { get ; set ; }
66-
67- [Parameter ]
68- public int Progress { get ; set ; }
69-
70- [Parameter ]
71- public int ProgressMin { get ; set ; } = 0 ;
7229
73- [Parameter ]
74- public int ProgressMax { get ; set ; } = 100 ;
7530
76- [Parameter ]
77- public int Width { get ; set ; } = 100 ;
78-
79- [Parameter ]
80- public int Height { get ; set ; } = 100 ;
31+ <style >
32+ .hex-progress-bar-container {
33+ position : relative ;
34+ display : flex ;
35+ align-items : center ;
36+ justify-content : center ;
37+ }
38+
39+ .hex-content-center {
40+ position : relative ;
41+ z-index : 1 ;
42+ display : flex ;
43+ flex-direction : column ;
44+ align-items : center ;
45+ justify-content : center ;
46+ text-align : center ;
47+ width : 100% ;
48+ height : 100% ;
49+ }
50+
51+ .hex-progress-bar-svg {
52+ position : absolute ;
53+ top : 0 ;
54+ left : 0 ;
55+ width : 100% ;
56+ height : 100% ;
57+ transition : stroke-dashoffset 0.5s ease-in-out ; /* Smooth transition for progress changes*/
58+ }
59+ </style >
8160
82- [Parameter ]
83- public int LineWidth { get ; set ; } = 8 ;
61+ @code {
62+ [Parameter ] public RenderFragment ? ChildContent { get ; set ; }
63+
64+ /// <summary >
65+ /// Value between 0 and 100
66+ /// </summary >
67+ [Parameter ] public double Progress { get ; set ; }
68+
69+ /// <summary >
70+ /// Size of SVG viewbox
71+ /// </summary >
72+ [Parameter ] public double Size { get ; set ; } = 100 ;
73+
74+ /// <summary >
75+ /// Color to use for ProgressBar
76+ /// </summary >
77+ [Parameter ] public string ProgressColor { get ; set ; } = " #E91E63" ;
78+
79+ /// <summary >
80+ /// Background Color
81+ /// </summary >
82+ [Parameter ] public string BackgroundColor { get ; set ; } = " #343434" ;
83+
84+ /// <summary >
85+ /// Thickness of Progress Bar
86+ /// </summary >
87+ [Parameter ] public double StrokeWidth { get ; set ; } = 8 ;
88+
8489
85- [Parameter ]
86- public Color ProgressColor { get ; set ; } = Color .Primary ;
90+ /// <summary >
91+ /// Radius of the Hexagon. Adjusted for stroke width and padding
92+ /// </summary >
93+ private double HexRadius => (Size / 2 ) - (StrokeWidth / 2 + 2 );
94+
95+ private const double HexCenterX = 50 ;
96+ private const double HexCenterY = 50 ;
8797
88- [ Parameter ]
89- public RenderFragment ? CenterContent { get ; set ; }
98+ private string HexagonPoints { get ; set ; } = " " ;
99+ private double HexagonPerimeter { get ; set ; }
90100
91- [ Parameter ]
92- public Color BadgeLineColor { get ; set ; } = Color . Secondary ;
101+ private string StrokeDashArray => HexagonPerimeter . ToString ( CultureInfo . InvariantCulture );
102+ private string StrokeDashOffset => ( HexagonPerimeter - ( HexagonPerimeter * Progress / 100 )). ToString ( CultureInfo . InvariantCulture ) ;
93103
94- [Parameter ]
95- public Color BadgeColor { get ; set ; } = Color .Tertiary ;
104+ protected override void OnInitialized ()
105+ {
106+ base .OnInitialized ();
107+ CalculateHexagonPoints ();
108+ CalculateHexagonPerimeter ();
109+ }
96110
97- readonly MudTheme _theme = new ();
98-
99- protected override async Task OnInitializedAsync ()
111+ protected override void OnParametersSet ()
100112 {
101- await base .OnInitializedAsync ();
113+ base .OnParametersSet ();
114+ CalculateHexagonPoints ();
115+ CalculateHexagonPerimeter ();
102116 }
103117
104- protected override async Task OnAfterRenderAsync ( bool firstRender )
118+ private void CalculateHexagonPoints ( )
105119 {
106- /*
107- It is worth mentioning that
108-
109- 1. To have the line color appear -- you cannot use the gradient value
110- 2. To see the progress bar you cannot use the fill or clip value -- those are for images
111- 3. These methods are called AFTER render because we want to make sure our
112- DOM elements are present before executing these scripts
113- */
114-
115- await JsRuntime .InvokeVoidAsync (" createHexagon" , new
116- {
117- width = Width ,
118- height = Height ,
119- container = " .hexagon-progress" ,
120- roundedCorners = true ,
121- lineWidth = LineWidth ,
122- lineColor = ColorUtil .GetCssValue (_theme , ProgressColor ),
123- scale = new { start = 0 , end = 1 , stop = MathUtil .GetNormalizedPercentage (Progress , ProgressMin , ProgressMax ) }
124- });
125-
126- await JsRuntime .InvokeVoidAsync (" createHexagon" , new
127- {
128- width = 68 ,
129- Height = 68 ,
130- container = " .hexagon-image" ,
131- roundedCorners = true ,
132- clip = true
133- });
120+ var effectiveRadius = Math .Max (1 , HexRadius );
134121
135- await JsRuntime .InvokeVoidAsync (" createHexagon" , new
136- {
137- container = " .hexagon-dark" ,
138- width = 26 ,
139- height = 28 ,
140- roundedCorners = true ,
141- roundedCornerRadius = 1 ,
142- lineColor = ColorUtil .GetCssValue (_theme , BadgeLineColor ),
143- fill = true
144- });
145-
146- await JsRuntime .InvokeVoidAsync (" createHexagon" , new
122+ var points = new List <string >();
123+
124+ for (var i = 0 ; i < 6 ; i ++ )
147125 {
148- container = " .hexagon-avatar-badge" ,
149- width = 32 ,
150- height = 36 ,
151- fill = true ,
152- roundedCorners = true ,
153- roundedCornerRadius = 1 ,
154- lineColor = ColorUtil .GetCssValue (_theme , BadgeColor )
155- });
126+ var angleDeg = 60 * i ;
127+ var angleRad = Math .PI / 180 * angleDeg ;
128+ var x = HexCenterX + effectiveRadius * Math .Cos (angleRad );
129+ var y = HexCenterY + effectiveRadius * Math .Sin (angleRad );
130+ points .Add ($" {x .ToString (CultureInfo .InvariantCulture )},{y .ToString (CultureInfo .InvariantCulture )}" );
131+ }
132+
133+ HexagonPoints = string .Join (" " , points );
134+ HexagonPerimeter = 6 * effectiveRadius ;
156135 }
157136
137+ private void CalculateHexagonPerimeter ()
138+ {
139+ // For a regular hexagon, perimeter is 6 * side length
140+ // Side length for a hexagon inscribed in a circle with radius R is also R
141+ HexagonPerimeter = 6 * HexRadius ;
142+ }
158143}
0 commit comments