Xamarin.Forms使用SkiaSharp绘制饼图时弧线颜色无法差异化设置求助
错误原因
- 全程使用同一个
SKPaint对象绘制所有弧线,且没有根据当前遍历的Profile对象修改画笔颜色,所有绘制都沿用了初始化时硬编码的SKColors.Green - 所有弧线都被添加到同一个
SKPath路径对象中,每次调用DrawPath都会重绘之前所有累积的弧线,即使修改了画笔颜色,最后一次绘制也会把所有弧线覆盖为集合最后一个对象的颜色 StartAngle属性的变更通知填写错误,绑定属性变更时错误触发了SweepAngle的通知
修复代码
直接替换你的OnCanvasViewPaintSurface方法即可:
void OnCanvasViewPaintSurface(System.Object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); SKPaint FilledCircle = new SKPaint { Style = SKPaintStyle.Fill, Color = Color.LightGray.ToSKColor(), }; // 弧线画笔仅初始化通用属性,颜色后续循环中动态修改 SKPaint arcPaint = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 200, IsAntialias = true // 加抗锯齿让边缘更平滑 }; SKPoint center = new SKPoint(info.Width / 2, info.Height / 2); SKRect _rect = new SKRect(center.X - 150, center.Y - 150, center.X + 150, center.Y + 150); // 初始化数据源 ProfileDetails = new ObservableCollection<Profile>() { new Profile{Id = 0,Name = "Dog", sKColors = SKColors.Red , Values = 541 }, new Profile{Id = 1,Name = "Cat",sKColors = SKColors.Pink ,Values = 2587 }, new Profile{Id = 2,Name = "Horse",sKColors = SKColors.Green, Values = 365 }, new Profile{Id = 3,Name = "Tiger",sKColors = SKColors.Blue, Values = 257 } }; // 计算总值 float _total = 0; foreach (var item in ProfileDetails) { _total += item.Values; } // 用局部变量存当前起始角度,避免依赖绑定属性的通知问题 float currentStartAngle = 0; foreach (var item in ProfileDetails) { // 计算当前弧的扫过角度 float percentage = item.Values / _total * 100; float sweepAngle = (percentage / 100) * 360 * -1; sweepAngle = (float)Math.Round(sweepAngle, 2); // 每次新建路径,避免和之前的弧累积 using (SKPath path = new SKPath()) { path.AddArc(_rect, currentStartAngle, sweepAngle); // 动态设置当前弧的颜色 arcPaint.Color = item.sKColors; canvas.DrawPath(path, arcPaint); } // 更新下一段弧的起始角度 currentStartAngle += sweepAngle; } canvas.DrawCircle(center, 80, FilledCircle); }
额外优化建议
- 数据源初始化不要放在
OnCanvasViewPaintSurface方法里,这个方法会频繁触发,每次都重新初始化集合会造成不必要的性能损耗,建议移到页面构造方法里 - 可以删掉没用的全局字段
_temp、_percentage、_arcAnglePoint,改用循环内局部变量更安全,避免多轮绘制时全局值累积出错
内容的提问来源于stack exchange,提问作者Samy Gray
相关产品推荐
相关产品推荐

