MAUI应用中FillPath忽略看似闭合路径内贝塞尔曲线的问题
路径填充失败:顶部环绕居中按钮的条形无法闭合填充
我需要绘制一个顶部环绕居中按钮的条形,已通过直线和贝塞尔曲线构建PathF对象,调用DrawPath能正常绘制轮廓,但调用FillPath时,路径因未被识别为闭合状态而无法填充。
DrawPath效果:
FillPath效果:
尝试调整代码近一小时仍未解决,以下是相关代码:
问题代码
IDrawable的Draw方法:
public void Draw(ICanvas canvas, RectF dirtyRect) { float buttonSize = 80; float width = dirtyRect.Width; float height = dirtyRect.Height; canvas.StrokeColor = Colors.Red; canvas.FillColor = Colors.Blue; canvas.StrokeSize = 1; float y1 = height / 2; // bar top float tX = width / 2; // x translation applied to all bezier curve points float tY = height / 2; // y translation applied to all bezier curve points float r = buttonSize * 1.5f / 2; // radius float c = 0.5522847498307933984022516322796f; float segmentWidth = (width - (r * 2)) / 2; PathF path = new PathF(0, y1); path.LineTo(segmentWidth, y1); // _____ path.MoveTo(width - segmentWidth, y1); // x path.LineTo(width, y1); // _____ path.LineTo(width, height); // | path.LineTo(0, height); // -------------- path.LineTo(0, y1); // | path.MoveTo(r + tX, 0 + tY); path.CurveTo(r + tX, c * r + tY, c * r + tX, r + tY, 0 + tX, r + tY); path.MoveTo(0 + tX, r + tY); path.CurveTo(-c * r + tX, r + tY, -r + tX, c * r + tY, -r + tX, 0 + tY); canvas.FillPath(path); }
布局代码:
<Grid ColumnDefinitions="*, Auto, *" RowDefinitions="*, 15*, 200"> <Button Grid.Row="0" Text="Draw" Clicked="Button_Clicked"/> <Grid Grid.Row="2" Grid.ColumnSpan="3" Padding="10, 10"> <GraphicsView x:Name="bottomBar" Grid.ColumnSpan="3"/> </Grid> </Grid>
解决方案
问题核心是你的路径是多个不连通的子路径,顶部曲线和下方条形没有连续连接,填充算法无法识别为单一闭合区域。需要移除不必要的MoveTo,让所有路径点连成一个连续的闭合环:
修改后的Draw方法代码:
public void Draw(ICanvas canvas, RectF dirtyRect) { float buttonSize = 80; float width = dirtyRect.Width; float height = dirtyRect.Height; canvas.StrokeColor = Colors.Red; canvas.FillColor = Colors.Blue; canvas.StrokeSize = 1; float y1 = height / 2; // bar top float tX = width / 2; // x translation applied to all bezier curve points float tY = height / 2; // y translation applied to all bezier curve points float r = buttonSize * 1.5f / 2; // radius float c = 0.5522847498307933984022516322796f; float segmentWidth = (width - (r * 2)) / 2; PathF path = new PathF(0, y1); // 左侧条形到曲线起点 path.LineTo(segmentWidth, y1); // 右侧下半圆曲线 path.CurveTo(c * r + tX, r + tY, r + tX, c * r + tY, r + tX, 0 + tY); // 上半圆曲线 path.CurveTo(r + tX, -c * r + tY, c * r + tX, -r + tY, 0 + tX, -r + tY); // 左侧下半圆曲线 path.CurveTo(-c * r + tX, -r + tY, -r + tX, -c * r + tY, -r + tX, 0 + tY); // 连接到右侧条形起点 path.CurveTo(-r + tX, c * r + tY, -c * r + tX, r + tY, width - segmentWidth, y1); // 右侧条形到右下角 path.LineTo(width, y1); path.LineTo(width, height); // 底部到左下角 path.LineTo(0, height); // 闭合路径回到起点 path.LineTo(0, y1); canvas.FillPath(path); }
关键说明
- 移除所有非必要的
MoveTo,保证路径从起点开始连续绘制 - 调整贝塞尔曲线的顺序,让每段曲线的起点与前一段的终点重合,形成连续的环绕部分
- 最后通过
LineTo回到初始点,确保路径完全闭合
内容的提问来源于stack exchange,提问作者Toto
相关产品推荐
相关产品推荐

