我以前从未使用过SkiaSharp或在编程中处理SVG和旋转点。我对矩阵的工作原理感到困惑,因为在研究时看起来非常复杂。我知道我可以将我的pivotX/Y点移动到中心,以便让我说我要旋转图像180度,并且它将与所有像素保持1:1。
注意:我没有创建这些SVG之一,它们是由公司内部的某个人创建的。
我正在使用Xamarin社区工具包获取自定义弹出窗口。我绘制的SVG总是倒置的。所以我想将其旋转180度,但我不确定如何将pivotX/Y设置在StarPath
或画布中心
的中心。
这个问题的整个重点是我学习如何在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);
}
}
当前更新的代码 - 我时间不多了,所以不能再把这个SkiaSharp
再搞砸了。我将会开发第二版本的游戏,这个版本更为复杂,所以我会回头再来处理这个问题。我对于SKMatrix.PostConcat
方法感到不满意,因为它使得这个方法变得过时
并且无法从任何地方访问。当有人失败一关时,我的星星有两种状态,而我必须采取非常错误的方法来实现它,但这是之后要修复的事情。此外,如果画布大小改变,整个绘画就会乱掉,所有东西都会乱成一锅粥。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;
var result = SKMatrix.CreateIdentity();
var translate = SKMatrix.CreateTranslation(-surfaceWidth / 2, -surfaceHeight / 2);
var rotate = SKMatrix.CreateRotationDegrees(180);
var translate2 = SKMatrix.CreateTranslation(surfaceWidth * 2, surfaceHeight);
SKMatrix.PostConcat(ref result, translate);
SKMatrix.PostConcat(ref result, rotate);
SKMatrix.PostConcat(ref result, translate2);
StarPath.Transform(result);
StarFill.Transform(result);
canvas.Scale(0.8f * Math.Min(surfaceWidth / bounds.Width, surfaceHeight / bounds.Height));
canvas.DrawPath(StarPath, WhiteOutline);
canvas.DrawPath(StarPath, Yellow);
canvas.DrawPath(StarFill, Shine);
if (DrawMain == true)
{
canvas.Scale(0.7f * Math.Min(surfaceWidth / bounds.Width, surfaceHeight / bounds.Height));
translate2 = SKMatrix.CreateTranslation(surfaceWidth * 2.5f, surfaceHeight * 2);
SKMatrix.PostConcat(ref result, translate2);
StarShine.Transform(result);
canvas.DrawPath(StarShine, White);
}
if (DrawSecond == true)
{
canvas.DrawPath(StarPath, WhiteOutline);
}
}
目前的情况是这样的。我看不到闪光,填充也没有填满整个星形……正确的图像应该是右侧的那个。