SkiaSharp ArcTo 方法不绘制曲线

SkiaSharp ArcTo Method does not draw curve

我正在尝试使用以下代码在 SkiaSharp canvas 视图上绘制弧线。

path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Large,
            SKPathDirection.Clockwise, new SKPoint(w/2, h));

但是它画的不是曲线,而是直线。如何做成曲线?

完整代码

 private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
 {

     var surface = e.Surface;
     var canvas = surface.Canvas;
     canvas.Clear(SKColors.White);

        var w = e.Info.Width;
        var h = e.Info.Height;

        var pathStroke3 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(240, 0, 100, 250),
            StrokeWidth = 5
        };

        var path3 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path3.MoveTo(0, h/2);
        path3.ArcTo(new SKPoint(0, h/2), 1.57f, SKPathArcSize.Large, SKPathDirection.Clockwise, new SKPoint(w/2, h));
        path3.LineTo(0, h);
        path3.Close();
        canvas.DrawPath(path3, pathStroke3);


 }

XAML

 <Grid x:Name="controlGrid" ColumnSpacing="0" RowSpacing="0" Padding="0" BackgroundColor="White" >
    <Grid.RowDefinitions>
        <RowDefinition Height="4*" />
        <RowDefinition Height="6*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <views:SKCanvasView PaintSurface="OnPainting" EnableTouchEvents="True" 
     Touch="OnTouch" HeightRequest="300" Grid.Row="0"/>
 </Grid>

您的 x 半径为零,因此 ArcTo 在从当前点到出口点的路径中添加一条线。

arcTo appends Line to xy if either radii are zero, or if last Path Point equals (x, y). arcTo scales radii r to fit last Path Point and xy if both are greater than zero but too small.

你可以这样做:

path3.ArcTo(new SKPoint(100, 100), 0, SKPathArcSize.Large, SKPathDirection.Clockwise, new SKPoint(w / 2, h));

但是我不知道你的绘图意图是什么; concave, convex, bounded, unbounded, 等等...但是其他一些使用 ConicTo 的例子可能更接近我认为你的意图:

path3.ConicTo(w / 3, h / 2, w / 2, h, 0.50f);

path3.ConicTo(0, h - (h / 5), w / 2, h, 0.50f);

您可能想查看官方文档以了解 ArcTo 如何解析为圆弧、二次曲线和移动:

根据@SushiHangover

的回复,我正在使用 ConicTo 进行以下操作

参考文献:

  1. Three Types of Bézier Curves - developer.xamarin
  2. Three Ways to Draw an Arc - developer.xamarin
  3. Experimental SkPath - skia.org

代码

private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
{

     var surface = e.Surface;
     var canvas = surface.Canvas;
     canvas.Clear(SKColors.White);

        var w = e.Info.Width;
        var h = e.Info.Height;
        var h12 = h - (h / 8);
        var h8 = h - (h / 6);
        var h4 = h - (h / 3);


        var pathStroke3 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(240, 0, 100, 250),
            StrokeWidth = 5
        };

        var path3 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path3.MoveTo(0, h4);
        path3.ConicTo(0, h8, w/2, h12, 0.50f);
        path3.LineTo(w/2, h);
        path3.LineTo(0, h);
        path3.Close();
        canvas.DrawPath(path3, pathStroke3);

        var pathStroke6 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.StrokeAndFill,
            Color = new SKColor(100,0, 240,  250),
            StrokeWidth = 5
        };
        var path6 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path6.MoveTo(w, h4);
        path6.ConicTo(w, h8, w / 2, h12, 0.50f);
        path6.LineTo(w / 2, h);
        path6.LineTo(w, h);
        path6.Close();
        canvas.DrawPath(path6, pathStroke6);


        var pathStroke4 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.Stroke,
            Color = new SKColor(0, 0, 255),
            StrokeWidth = 5
        };

        var path4 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path4.MoveTo(0, h4);
        path4.LineTo(w / 2, h4);
        canvas.DrawPath(path4, pathStroke4);


        var pathStroke5 = new SKPaint
        {
            IsAntialias = true,
            Style = SKPaintStyle.Stroke,
            Color = new SKColor(0, 255, 0),
            StrokeWidth = 5
        };
        var path5 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path5.MoveTo(0, h8);
        path5.LineTo(w / 2, h8);
        canvas.DrawPath(path5, pathStroke5);

        var path7 = new SKPath { FillType = SKPathFillType.EvenOdd };
        path5.MoveTo(w/4, h8);
        path5.LineTo(w /4, h);
        canvas.DrawPath(path5, pathStroke5);

  }