Radial Chart - Stacked
An animated upper-semicircle radial chart with two stacked arc segments sharing the same ring. Both segments grow together, filling 180° proportionally. The total is displayed at the center. Powered by a Power Apps Image control. Inspired by the shadcn/ui Radial Chart - Stacked.
Radial Chart - Stacked
January - June 2024
Trending up by 5.2% this month
Showing total visitors for the last 6 months
How to Use
- On your screen's OnVisible, add: Set(varRdlStkAnimate, true)
- Paste the copied YAML into Power Apps Studio (Ctrl+V).
- Both arc segments grow from 0 to full proportionally over 1.2 seconds.
- To replay the animation: Set(varRdlStkAnimate, false); Set(varRdlStkAnimate, true)
- Change Value 1 and Value 2 to control segment proportions. The total is always displayed in the center.
Problem Solved
Renders an animated stacked radial chart with two segments sharing a single 180° semicircle ring in a Power Apps Image control. Uses Cos()/Sin() with Radians() for arc endpoints, splits arcs at the top midpoint to avoid large-arc-flag animation glitches, and an easing cubic-out curve driven by a Timer control.
Integration
Set Value 1 / Label 1 for the first segment (e.g. Mobile) and Value 2 / Label 2 for the second (e.g. Desktop). The proportions are computed automatically: Segment 1 fills value1/(value1+value2)×180°, Segment 2 fills the rest. Use Color 1 and Color 2 to distinguish them. The Center Label appears below the total count.
YAML Code
- conRdlStkChart:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
BorderColor: =RGBA(226, 232, 240, 1)
BorderStyle: =BorderStyle.Solid
BorderThickness: =1
DropShadow: =DropShadow.Regular
Fill: =RGBA(255, 255, 255, 1)
Height: =276
RadiusBottomLeft: =12
RadiusBottomRight: =12
RadiusTopLeft: =12
RadiusTopRight: =12
Width: =380
Children:
- tmrRdlStkAnimate:
Control: Timer@2.1.0
Properties:
Duration: =1200
Height: =1
OnTimerEnd: =Set(varRdlStkAnimate, false)
Repeat: =false
Start: =varRdlStkAnimate
Visible: =false
Width: =1
X: =0
Y: =0
- lblRdlStkTitle:
Control: Label@2.5.1
Properties:
Align: =Align.Center
Color: =RGBA(15, 23, 42, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Bold
Height: =24
Size: =14
Text: ="Radial Chart - Stacked"
Width: =340
X: =20
Y: =14
- lblRdlStkDesc:
Control: Label@2.5.1
Properties:
Align: =Align.Center
Color: =RGBA(100, 116, 139, 1)
Font: =Font.'Open Sans'
Height: =20
Size: =12
Text: ="January - June 2024"
Width: =340
X: =20
Y: =44
- rectRdlStkHeader:
Control: Rectangle@2.3.0
Properties:
Fill: =RGBA(226, 232, 240, 1)
Height: =1
Width: =380
X: =0
Y: =68
- imgRdlStkChart:
Control: Image@2.2.3
Properties:
Height: =120
Width: =352
X: =14
Y: =72
Image: |-
=With(
{
_mob: Value(570),
_dsk: Value(1260),
_p: Min(1, tmrRdlStkAnimate.Value / 1200),
_c1: "#3b82f6",
_c2: "#f97316"
},
With(
{ _ease: 1 - Power(Max(0, 1 - _p), 3), _total: Max(1, _mob + _dsk) },
With(
{ _mob_deg: _ease * (_mob / _total) * 180 },
With(
{ _mob_ang: Radians(180 + _mob_deg) },
With(
{
_ox: Int(Round(208 + 110 * Cos(_mob_ang), 0)),
_oy: Int(Round(135 + 110 * Sin(_mob_ang), 0)),
_ix: Int(Round(208 + 80 * Cos(_mob_ang), 0)),
_iy: Int(Round(135 + 80 * Sin(_mob_ang), 0))
},
"data:image/svg+xml;utf8, " & EncodeUrl(
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 10 416 145'>" &
"<path d='M 98 135 A 110 110 0 0 1 208 25 A 110 110 0 0 1 318 135 L 288 135 A 80 80 0 0 0 208 55 A 80 80 0 0 0 128 135 Z' fill='#e2e8f0'/>" &
If(_mob_deg > 0.5,
If(_mob_deg > 90,
"<path d='M 98 135 A 110 110 0 0 1 208 25 A 110 110 0 0 1 " &
Text(_ox, "0") & " " & Text(_oy, "0") &
" L " & Text(_ix, "0") & " " & Text(_iy, "0") &
" A 80 80 0 0 0 208 55 A 80 80 0 0 0 128 135 Z' fill='" & _c1 & "'/>",
"<path d='M 98 135 A 110 110 0 0 1 " &
Text(_ox, "0") & " " & Text(_oy, "0") &
" L " & Text(_ix, "0") & " " & Text(_iy, "0") &
" A 80 80 0 0 0 128 135 Z' fill='" & _c1 & "'/>"
),
""
) &
If(_ease * 180 - _mob_deg > 0.5,
If(_mob_deg < 90,
"<path d='M " & Text(_ox, "0") & " " & Text(_oy, "0") &
" A 110 110 0 0 1 208 25 A 110 110 0 0 1 318 135 L 288 135" &
" A 80 80 0 0 0 208 55 A 80 80 0 0 0 " &
Text(_ix, "0") & " " & Text(_iy, "0") & " Z' fill='" & _c2 & "'/>",
"<path d='M " & Text(_ox, "0") & " " & Text(_oy, "0") &
" A 110 110 0 0 1 318 135 L 288 135 A 80 80 0 0 0 " &
Text(_ix, "0") & " " & Text(_iy, "0") & " Z' fill='" & _c2 & "'/>"
),
""
) &
"<text x='208' y='119' text-anchor='middle' dominant-baseline='middle' font-family='Arial,sans-serif' font-size='26' font-weight='bold' fill='#0f172a'>" & Text(Int(_mob + _dsk), "#,##0") & "</text>" &
"<text x='208' y='140' text-anchor='middle' font-family='Arial,sans-serif' font-size='11' fill='#64748b'>" & "Visitors" & "</text>" &
"</svg>"
)
)
)
)
)
)
- imgRdlStkDot1:
Control: Image@2.2.3
Properties:
Fill: =ColorValue("#3b82f6")
Height: =10
Image: =Blank()
RadiusBottomLeft: =5
RadiusBottomRight: =5
RadiusTopLeft: =5
RadiusTopRight: =5
Width: =10
X: =102
Y: =198
- lblRdlStkLeg1:
Control: Label@2.5.1
Properties:
Color: =RGBA(15, 23, 42, 1)
Font: =Font.'Open Sans'
Height: =14
Size: =10
Text: ="Mobile"
Width: =76
X: =118
Y: =196
- imgRdlStkDot2:
Control: Image@2.2.3
Properties:
Fill: =ColorValue("#f97316")
Height: =10
Image: =Blank()
RadiusBottomLeft: =5
RadiusBottomRight: =5
RadiusTopLeft: =5
RadiusTopRight: =5
Width: =10
X: =202
Y: =198
- lblRdlStkLeg2:
Control: Label@2.5.1
Properties:
Color: =RGBA(15, 23, 42, 1)
Font: =Font.'Open Sans'
Height: =14
Size: =10
Text: ="Desktop"
Width: =76
X: =218
Y: =196
- btnRdlStkLeg1Hit:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Transparent
Height: =16
OnSelect: =If(varRdlStkTooltipIdx = 1, Set(varRdlStkTooltipIdx, 0), Set(varRdlStkTooltipIdx, 1))
Text: =""
Width: =96
X: =100
Y: =194
- btnRdlStkLeg2Hit:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Transparent
Height: =16
OnSelect: =If(varRdlStkTooltipIdx = 2, Set(varRdlStkTooltipIdx, 0), Set(varRdlStkTooltipIdx, 2))
Text: =""
Width: =96
X: =200
Y: =194
- rectRdlStkFooter:
Control: Rectangle@2.3.0
Properties:
Fill: =RGBA(226, 232, 240, 1)
Height: =1
Width: =380
X: =0
Y: =214
- lblRdlStkTrend:
Control: Label@2.5.1
Properties:
Align: =Align.Center
Color: =RGBA(15, 23, 42, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Semibold
Height: =20
Size: =12
Text: ="Trending up by 5.2% this month"
Width: =340
X: =20
Y: =222
- lblRdlStkDateRange:
Control: Label@2.5.1
Properties:
Align: =Align.Center
Color: =RGBA(100, 116, 139, 1)
Font: =Font.'Open Sans'
Height: =20
Size: =11
Text: ="Showing total visitors for the last 6 months"
Width: =340
X: =20
Y: =246
- conRdlStkTooltip:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
BorderColor: =RGBA(226, 232, 240, 1)
BorderStyle: =BorderStyle.Solid
BorderThickness: =1
DropShadow: =DropShadow.Regular
Fill: =RGBA(255, 255, 255, 1)
Height: =65
RadiusBottomLeft: =7
RadiusBottomRight: =7
RadiusTopLeft: =7
RadiusTopRight: =7
Visible: =varRdlStkTooltipIdx > 0
Width: =120
X: =If(varRdlStkTooltipIdx = 1, 80, 180)
Y: =130
Children:
- lblTooltipRdlStkLabel:
Control: Label@2.5.1
Properties:
Color: =RGBA(100, 116, 139, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Semibold
Height: =16
Size: =10
Text: =If(varRdlStkTooltipIdx = 1, "Mobile", "Desktop")
Width: =104
X: =8
Y: =5
- imgTooltipRdlStkDot:
Control: Image@2.2.3
Properties:
Fill: =If(varRdlStkTooltipIdx = 1, ColorValue("#3b82f6"), ColorValue("#f97316"))
Height: =7
Image: =Blank()
RadiusBottomLeft: =3
RadiusBottomRight: =3
RadiusTopLeft: =3
RadiusTopRight: =3
Width: =7
X: =8
Y: =27
- lblTooltipRdlStkValue:
Control: Label@2.5.1
Properties:
Color: =RGBA(15, 23, 42, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Semibold
Height: =16
Size: =10
Text: =Text(Int(If(varRdlStkTooltipIdx = 1, Value(570), Value(1260))), "#,##0")
Width: =90
X: =20
Y: =25
- lblTooltipRdlStkPct:
Control: Label@2.5.1
Properties:
Color: =RGBA(100, 116, 139, 1)
Font: =Font.'Open Sans'
Height: =14
Size: =9
Text: =Text(Round(If(varRdlStkTooltipIdx = 1, Value(570), Value(1260)) / Max(1, Value(570) + Value(1260)) * 100, 1)) & "% of total"
Width: =104
X: =8
Y: =46Implementation
Copies the customized component code directly to your clipboard. Use Ctrl+V in Power Apps Studio.
Something not pasting right? Troubleshooting guide