How to animate a simple smooth rotation

MarcusRungeMarcusRunge DEMember ✭✭

Hello,
I have the following working Skiasharp object:

public class CircleButtonRotor : SKCanvasView
    {
        public CircleButtonRotor()
        {
            PaintSurface += CanvasView_PaintSurface;
        }

        private void CanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            SKImageInfo info = e.Info;
            SKSurface surface = e.Surface;
            SKCanvas canvas = surface.Canvas;
            float scale = (float)info.Width / 256f;
            canvas.Clear();
            SKPaint skPaint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                Color = Color.FromHex("#BB171D").ToSKColor(),
                StrokeWidth = 16 * scale,
                IsAntialias = true
            };

            SKRect rect = new SKRect(8f * scale, 8f * scale, 248f * scale, 248f * scale);

            using (SKPath path = new SKPath())
            {
                path.AddArc(rect, 0, 30);
                canvas.DrawPath(path, skPaint);
            }
        }
    }

How do I get this endless rotating, one full Rotation per Minute, smoothly without stopping?

Answers

  • mattleibowmattleibow ZAXamarin Team Xamurai

    This obviously depends on the platform, but should be very similar. For example on Xamarin.Forms you could do something like this:

    // fields
    float start = 0;
    Stopwatch watch = new Stopwatch();
    
    void SetupTimer()
    {
        // 30 fps
        var fps = TimeSpan.FromSeconds(1.0 / 30.0);
    
        // set up and start timer
        watch.Start();
        start = 0;
        Device.StartTimer(fps, () =>
        {
            // get elapsed time
            var time = (float)watch.Elapsed.TotalMinutes;
            watch.Restart();
    
            // get the elapsed rotation
            start += (360 * time) % 360;
    
            // refresh the screen
            InvalidateSurface();
    
            // continue 
            return true;
        });
    }
    

    A good resource is this: https://developer.xamarin.com/guides/xamarin-forms/advanced/skiasharp/
    It is aimed for Xamarin.Forms developers, but the SkiaSharp bits are exactly the same.

  • MarcusRungeMarcusRunge DEMember ✭✭

    Thanks for your help, what do you think about this Approach:

        public class CircleButton128BlueRotor : SKCanvasView
            {
                bool _activated;
                public CircleButton128BlueRotor()
                {
                    _activated = false;
                    PaintSurface += CanvasView_PaintSurface;
                    PropertyChanged += CircleButton128BlueRotor_PropertyChanged;
                }
    
                private async void CircleButton128BlueRotor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
                {
                    if (!_activated && IsVisible)
                    {
                        _activated = true;
                        while (_activated)
                        {
                            await this.RotateTo(360, 5000);
                            Rotation = 0;
                        }
                    }
    
                    if (!_activated && e.PropertyName.Equals("IsVisible") && IsVisible)
                    {
                        _activated = true;
                        while (_activated)
                        {
                            await this.RotateTo(360, 5000);
                            Rotation = 0;
                        }
                    }
                }
    
                private void CanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
                {
                    SKImageInfo info = e.Info;
                    SKSurface surface = e.Surface;
                    SKCanvas canvas = surface.Canvas;
                    float scale = (float)info.Width / 64f;
                    canvas.Clear();
                    SKPaint skPaint = new SKPaint
                    {
                        Style = SKPaintStyle.Stroke,
                        Color = Color.FromHex("#0B71A6").ToSKColor(),
                        StrokeWidth = 4 * scale,
                        IsAntialias = true
                    };
    
                    SKRect rect = new SKRect(2f * scale, 2f * scale, 62f * scale, 62f * scale);
    
                    using (SKPath path = new SKPath())
                    {
                        path.AddArc(rect, -90, 30);
                        canvas.DrawPath(path, skPaint);
                    }
                }
            }
    
  • mattleibowmattleibow ZAXamarin Team Xamurai

    That could work...

    You are rotating the entire canvas, so you could get away with not having to draw multiple times. Just remember that a rotation may cause a layout and will keep firing the property changed event.

    I just want to point out that you have almost duplicate code in the property changing. You may also want check to see if you want this to stop rotating. You currently have no way to stop it - but this may not be something you want to do.

Sign In or Register to comment.