Avalonia 里 5 行 XAML 快速画出会动的环形进度条
【免费下载链接】AvaloniaDevelop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The future of .NET UI项目地址: https://gitcode.com/GitHub_Trending/ava/Avalonia
刚拿到一个跨平台指标面板的需求:Windows、macOS、Linux 上同一个界面,中间一个会随数值变长的环形进度条。用 Avalonia 图形绘制实现它只需要三样东西:Canvas当画布,Path的弧线命令画弧,TextBlock放读数——全程纯 XAML,四个平台渲染结果一致。下面按"先定位、再画弧、后叠层、最后让它动"的顺序拆开讲。
Canvas 在布局里管什么
Avalonia 的面板(Panel,负责摆放子元素的容器)大多会自己做排列,Canvas是例外:它对子元素不做任何排列,每个子元素落在哪完全由四个附加属性决定:
Canvas.Left/Canvas.Top:左边缘距画板左边缘、上边缘距画板上边缘的像素数,最常用;Canvas.Right/Canvas.Bottom:反过来从右缘、下缘量起,适合"贴边"的元素;- 同一方向写了两边时,Left 和 Top 优先;一个都没写,元素就落在
(0,0)。
坐标系约定:原点在画板左上角,x 向右、y 向下增长(与数学坐标相反),单位是 DIP(设备无关像素,可写小数,1 个单位对应 1 个逻辑像素)。另外Canvas自身测量结果为 0,不占父容器的布局空间,可以直接盖在任何面板上当纯绘图层。
XAML 画形状:先选对元件
画形状前先用 src/Avalonia.Controls/Shapes/ 目录选对元件:
| 元件 | 干什么的 | 关键属性 |
|---|---|---|
Path | 弧线、任意轮廓,本例主角 | Data(命令字符串)、Stroke、StrokeLineCap |
Line | 指针、分隔线、短刻度 | StartPoint、EndPoint |
Ellipse | 中心圆帽、圆点标记 | Width、Height、Fill |
Rectangle | 直角或圆角底板 | RadiusX、RadiusY、Fill |
没有"万能控件",只有"最省事的控件":环形进度用Path加粗描边,中心圆帽用Ellipse,读数用TextBlock。
弧线用哪条路径命令
环形的"环"就是一条圆弧。Data属性是一串路径命令(Path 标记解析器源码),四个命令覆盖本例全部需求:
M x,y:把画笔移到起点,这一笔不画;L x,y:从当前位置画直线到 (x,y);A rx ry rot large sweep x,y:画一段圆弧到 (x,y),rx ry是椭圆半径,large选 180° 以上的大弧还是小弧,sweep选走向;Z:直线回到起点并闭合。
取 240 宽画板,圆心 (120,120)、半径 90。135° 方向(左下)的弧端点算出来是 (75.9,184.1),45° 方向(右下)是 (184.1,184.1),两个点正好都落在 y=184.1 上:
<Canvas Width="240" Height="240"> <Path Data="M 75.9,184.1 A 90,90 0 0 1 184.1,184.1" Stroke="#2196F3" StrokeThickness="16" StrokeLineCap="Round"/> </Canvas>0 0 1这段里最后一个 1 决定从 75.9 到 184.1 走上方半圆;写成 0 会从下方绕过去,方向正好反了。StrokeLineCap="Round"给两端加上圆形端帽,和 16 粗细的弧连成圆头效果。
线条和文字谁压住谁
Canvas 子元素按书写顺序渲染,后写的盖在先写的上面,想精确控制就加Canvas.ZIndex:
<Path Canvas.Left="12" Data="M 37.9,146.1 A 70,70 0 0 1 142.1,146.1" Stroke="#2196F3" StrokeThickness="12" StrokeLineCap="Round"/> <Ellipse Canvas.Left="104" Canvas.Top="104" Width="32" Height="32" Fill="#FF5722" Canvas.ZIndex="1"/> <TextBlock Canvas.Left="84" Canvas.Top="112" Text="62%" FontSize="18" Canvas.ZIndex="2"/>弧线、中心圆帽、读数三行就是整个组件的骨架:圆帽盖在弧的交汇点上,文字用ZIndex顶到最上层,互相不打架。
让它动起来
静态环有了,怎么变长?把数值接到绑定上就行。Slider的Maximum默认就是 100,把它的Value绑给一个圆环的宽度,拖动滑块时圆环实时变化:
<Ellipse Canvas.Left="88" Canvas.Top="88" Width="64" Height="64" Fill="{Binding ElementName=knob, Path=Value}"/>一行绑定,不用写一行 C#。如果做的是指针式表盘,思路换成旋转:给指针Line挂RotateTransform,围绕表盘中心设CenterX/CenterY作轴心,动画驱动Angle属性即可。
这些坑我替你踩过了
- 只写了
Canvas.Left忘了Canvas.Top:Top 默认是 NaN,元素会塌到 y=0,看起来像"飞走了"。显式写全两个方向。 - 线条端点是方头,和粗描边接茬难看:加
StrokeLineCap="Round"。 - 读数被后面的图形盖住:不是文字的问题,是书写顺序的问题,
Canvas.ZIndex顶上去。 - 想动态改弧长:
Data是Path的普通属性,可以直接用绑定表达式拼命令串,不必退回去手写StreamGeometry。 - 画面里小图形很多:把重复的短线段合并进一条
Path的多个子路径里,绘制对象少一半,渲染压力小一半。
完整组件就是上面三块拼在一起:一个 240x240 的Canvas,里面一条蓝色弧线Path、一个橙色中心圆帽Ellipse、一个百分比TextBlock,再配一个Slider做数据源,总共不到 20 行 XAML。
最后三句话收束:Canvas 只管钉坐标,不管排列;弧形走Path的A命令加粗描边,不用任何高级技巧;书写顺序加ZIndex决定谁压住谁。
【免费下载链接】AvaloniaDevelop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The future of .NET UI项目地址: https://gitcode.com/GitHub_Trending/ava/Avalonia
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考