【问题标题】:SkiaSharp set new rotation point at the centre of the canvasSkiaSharp 在画布中心设置新的旋转点
【发布时间】:2022-11-08 15:41:46
【问题描述】:

我从未在编程中使用过 SkiaSharp 或处理过 SVG 和旋转点。我对矩阵的工作方式感到困惑;研究时看起来很复杂。我知道我可以将我的 pivotX/Y 点移动到中心,让我说我想将图像旋转 180 度,并且所有像素都是 1:1。

笔记:我没有创建任何这些 SVG,它们是由公司内部的某个人制作的。

我正在使用 Xamarin 社区工具包来获取自定义弹出窗口。我画的 SVG 总是倒着画的。所以我想将它旋转 180 度,但我不确定如何将 pivotX/Y 设置在StarPathCanvas center 的中心。

这个问题的重点,所以我可以学习如何在 SkiaSharp 中操作矩阵,并能够通过指定 degrees width / 2 height / 2 来制作一种旋转路径的方法

Xamarin 代码

<?xml version="1.0" encoding="utf-8" ?>
<xct:Popup xmlns="http://xamarin.com/schemas/2014/forms"
           xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
           x:Class="uCue_Game.View.LostLifePopUp"
           xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
           xmlns:sksh="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
           Size="400, 400"
           Color="Transparent">

    <StackLayout BackgroundColor="Black"
          Opacity="1">

        <sksh:SKCanvasView x:Name="canvasView"
                           PaintSurface="canvasView_PaintSurface"
                           HorizontalOptions="FillAndExpand"
                           VerticalOptions="FillAndExpand" 
                           HeightRequest="300"
                           Opacity="1"/>
        <Label Text="Wrong Answer" 
               HorizontalOptions="FillAndExpand"
               VerticalOptions="FillAndExpand"
               FontSize="15"
               TextColor="White"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center"
               Opacity="1"/>
    </StackLayout>
</xct:Popup>

C# 代码

public partial class LostLifePopUp : Popup
{
    SKPath StarPath = SKPath.ParseSvgPathData("M492" +
    " 348 c16 -18 47 -67 69 -110 38 -76 40 -78 77 -78 55 -1 156 -24 186 -43 42" +
    " -28 34 -61 -27 -120 -29 -29 -70 -63 -90 -77 -24 -16 -35 -30 -31 -40 18 -48" +
    " 44 -170 44 -211 0 -44 -3 -49 -25 -55 -31 -8 -144 27 -209 64 l-47 27 -97 -47" +
    " c-102 -50 -157 -65 -181 -49 -20 13 -16 97 9 195 l20 79 -58 61 c-69 73 -102" +
    " 118 -102 141 0 22 66 50 177 75 l90 21 22 53 c12 29 35 74 51 100 38 59 76 63" +
    " 122 14z");

    SKPath StarFill = SKPath.ParseSvgPathData("M487" +
    " 363 c21 -24 58 -71 83 -105 32 -46 51 -64 74 -69 65 -14 201 -56 213 -65 28" +
    " -23 2 -34 -85 -35 -109 -1 -229 -31 -336 -85 -136 -69 -223 -82 -298 -43 -32" +
    " 17 -98 73 -98 84 0 4 10 18 23 32 12 14 32 37 44 51 12 15 35 29 50 33 15 4" +
    " 49 15 75 26 38 16 51 29 76 76 50 94 89 142 116 142 15 0 38 -16 63 -42z");

    SKPath StarShine = SKPath.ParseSvgPathData(
        "M0 1215 m0 -1215 m1260 0 m1260 0 m0 1215 m0 1215 m-1260 0 m-1260 0 m0" +
        " -1215z m1395 838 c35 -35 95 -164 95 -204 0 -55 -64 -92" +
        " -117 -69 -56 25 -68 54 -68 166 0 105 10 134 45 134 9 0 30 -12 45 -27z");

    SKPaint StrokeRed = new SKPaint
    {
        Style = SKPaintStyle.StrokeAndFill,
        Color = SKColors.Red,
        StrokeWidth = 5,
        StrokeCap = SKStrokeCap.Round,
        StrokeJoin = SKStrokeJoin.Round
    };

    SKPaint FillYellow = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = SKColors.Yellow,
        StrokeWidth = 5,
        StrokeCap = SKStrokeCap.Round,
        StrokeJoin = SKStrokeJoin.Round
    };

    SKPaint GoldShine = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Green,
        StrokeWidth = 40,
        StrokeCap = SKStrokeCap.Round,
        StrokeJoin = SKStrokeJoin.Round
    };

    public LostLifePopUp()
    {
        InitializeComponent();

    }

    private void canvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        SKRect bounds;
        StarPath.GetBounds(out bounds);

        var surface = e.Surface;
        var surfaceWidth = e.RawInfo.Width;
        var surfaceHeight = e.RawInfo.Height;

        var canvas = surface.Canvas;

        canvas.Flush();
        canvas.Clear();

        var rot = SKMatrix.CreateRotationDegrees(37, surfaceWidth / 2 - 50, surfaceHeight / 2);
        canvas.SetMatrix(rot);

        canvas.Translate(surfaceWidth / 2, surfaceHeight / 2);
        canvas.Scale(0.9f * Math.Min(surfaceWidth / bounds.Width,
                                    surfaceHeight / bounds.Height));
        canvas.Translate(-bounds.MidX, -bounds.MidY);

        canvas.DrawPath(StarShine, GoldShine);
        canvas.DrawPath(StarPath, StrokeRed);
        canvas.DrawPath(StarFill, FillYellow);
    }
}

这是目前的样子。我看不到 Shine,也看不到填充实际上填满了整个星星......正确的图像就是它应该看起来的样子。

【问题讨论】:

  • 我没有详细查看您的矩阵变换,但问题通常是找到正确的命令在其中进行转换。这需要一些试验和错误。如果您尝试“一次一个”的变换,最容易得到正确的结果。从仅旋转加图像开始,画布中没有其他内容。您可能需要先进行少量旋转,以确切了解它在做什么。它是围绕一个角旋转,还是围绕一个边缘的中间旋转?接下来,尝试平移和旋转。尝试两种方式:首先翻译会发生什么?先旋转。
  • ...规模是最后的添加一个。因为它如何与旋转和平移相互作用通常是不明显的。希望你可以在开头或结尾添加它[一旦你有旋转+翻译做你想做的事],其中一个地方会起作用。

标签: c# xamarin.forms skiasharp


【解决方案1】:

在您的情况下,要旋转 180 度并平移,只需尝试以下代码:

SKRect bounds;       
StarPath.GetTightBounds(out bounds);
canvas.RotateDegrees(180, bounds.MidX, bounds.MidY); // rotate 180
canvas.Translate(surfaceWidth/2 - bounds.MidX, - (surfaceHeight / 2 - bounds.MidY)); // Translate

更多信息,您可以参考The Rotate Transform

希望我的回答能帮到你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-05
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 2015-01-06
    • 2016-07-07
    相关资源
    最近更新 更多