# SkiaSharp/Skia - Rotating shapes around their own axis

96 Reputation points
2021-03-22T09:02:51.88+00:00

I am learning SkiaSharp and I'd like to have N shapes rotating around their own vertical axis, but I can't find a way to do it.

This is the result of my OnDraw method (rotationView is updated every N milliseconds):

`````` protected override void OnDraw(SKCanvas canvas, int width, int height)
{
int i = 0;
int step = 0;
List<SKRect> rects = new List<SKRect>();

// get the 2D equivalent of the 3D matrix
var rotationMatrix = rotationView.Matrix;

// get the properties of the rectangle
var length = Math.Min(width / 6, height / 6);

canvas.Clear(EffectMedia.Colors.XamarinLightBlue);

foreach (var n in numbers)
{
var rect = new SKRect(0 + step, 0, 100 + step, 100);
step += 120;
}

//var sideHoriz = rotationMatrix.MapPoint(new SKPoint(0, 1)).Y > 0;
var sideVert = rotationMatrix.MapPoint(new SKPoint(1, 0)).X > 0;

var paint = new SKPaint
{
Color = sideVert ? EffectMedia.Colors.XamarinPurple : EffectMedia.Colors.XamarinGreen,
Style = SKPaintStyle.Fill,
IsAntialias = true
};

// first do 2D translation to the center of the screen
canvas.Translate((width - (120 * numbers.Count)) / 2, height / 2);

// The following line is disabled because it makes the whole canvas rotate!
// canvas.Concat(ref rotationMatrix);

foreach (var n in numbers)
{
canvas.RotateDegrees((float)-3);
canvas.DrawRoundRect(rects[i], 30, 30, paint);

new SKPoint(0, 0), new SKPoint(0, length * 2),
new[] { paint.Color.WithAlpha(127), paint.Color.WithAlpha(0) },
null,

{
Style = SKPaintStyle.Fill,
IsAntialias = true,
BlendMode = SKBlendMode.SoftLight
};

foreach (var r in rects)
{
r.Offset(0, 105);
}

i++;
}
}
``````

I tried using SKPath + Transform, saving&restoring the rotationMatrix and/or the canvas but I can't find a way to have 6 rotating boxes around their own axis.

Do you have any hint on how that can be achieved? Do I need N rotation matrices?

Thanks!

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
4,818 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,185 questions

1. 96 Reputation points
2021-03-22T10:55:55.01+00:00

My goal would be to have N shapes rotating around their axes, something like:

Would could be a viable approach in SkiaSharp (I'd just need some directions)?

Thanks :)

2. 23,846 Reputation points
2021-03-25T10:07:30.197+00:00

Hi, Sal-Datoccio. According to my search, it doesn't provide a way to get the drawing sharp. A workaround is using SKCanvasView to draw each sharp one separately, and rotate the skCanvasViews.

Here is the related code, you could refer to it.

``````public partial class TestPage : ContentPage
{
public TestPage()
{
Title = "Testing for Animated Rotation";

canvasView1 = new SKCanvasView() { AutomationId = "1" };
canvasView2 = new SKCanvasView() { AutomationId = "2" };
canvasView3 = new SKCanvasView() { AutomationId = "3" };
canvasView4 = new SKCanvasView() { AutomationId = "4" };
canvasView5 = new SKCanvasView() { AutomationId = "5" };
canvasView6 = new SKCanvasView() { AutomationId = "6" };

canvasView1.PaintSurface += OnCanvasViewPaintSurface;
canvasView2.PaintSurface += OnCanvasViewPaintSurface;
canvasView3.PaintSurface += OnCanvasViewPaintSurface;
canvasView4.PaintSurface += OnCanvasViewPaintSurface;
canvasView5.PaintSurface += OnCanvasViewPaintSurface;
canvasView6.PaintSurface += OnCanvasViewPaintSurface;
Content = new StackLayout()
{
HorizontalOptions = LayoutOptions.Center,
Orientation = StackOrientation.Horizontal,
Children = { canvasView1, canvasView2, canvasView3, canvasView4, canvasView5, canvasView6 }
};

// Measure the text
textPaint.MeasureText(text1, ref textBounds);
}

protected override void OnAppearing()
{
base.OnAppearing();

new Animation((value) =>
{
yRotationDegrees = 360 * (float)value;
canvasView1.InvalidateSurface();
canvasView2.InvalidateSurface();
canvasView3.InvalidateSurface();
canvasView4.InvalidateSurface();
canvasView5.InvalidateSurface();
canvasView6.InvalidateSurface();
}).Commit(this, "yRotationAnimation", length: 1000, repeat: () => true);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
//this.AbortAnimation("xRotationAnimation");
this.AbortAnimation("yRotationAnimation");
//this.AbortAnimation("zRotationAnimation");
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;

canvas.Clear();

// Find center of canvas
float xCenter = info.Width / 2;
float yCenter = info.Height / 2;

// Translate center to origin
SKMatrix matrix = SKMatrix.MakeTranslation(-xCenter, -yCenter);

float scale = 1;
SKMatrix.PostConcat(ref matrix, SKMatrix.MakeScale(scale, scale));

// Calculate composite 3D transforms
float depth = 0.75f * scale * textBounds.Width;

SKMatrix44 matrix44 = SKMatrix44.CreateIdentity();
//matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, xRotationDegrees));
matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, yRotationDegrees));
//matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, zRotationDegrees));

SKMatrix44 perspectiveMatrix = SKMatrix44.CreateIdentity();
perspectiveMatrix[3, 2] = -1 / depth;
matrix44.PostConcat(perspectiveMatrix);

// Concatenate with 2D matrix
SKMatrix.PostConcat(ref matrix, matrix44.Matrix);

// Translate back to center
SKMatrix.PostConcat(ref matrix,
SKMatrix.MakeTranslation(xCenter, yCenter));

// Set the matrix and display the text
canvas.SetMatrix(matrix);
float xText = xCenter - textBounds.MidX;
float yText = yCenter - textBounds.MidY;

SKCanvasView view = sender as SKCanvasView;
switch (view.AutomationId)
{
case "1":
canvas.DrawText(text1, xText, yText, textPaint);
break;
case "2":
canvas.DrawText(text2, xText, yText, textPaint);
break;
case "3":
canvas.DrawText(text3, xText, yText, textPaint);
break;
case "4":
canvas.DrawText(text4, xText, yText, textPaint);
break;
case "5":
canvas.DrawText(text5, xText, yText, textPaint);
break;
case "6":
canvas.DrawText(text6, xText, yText, textPaint);
break;
}
}
}
``````