# Sample with SkiaSharp

In this tutorial we'll see how integrate SkiaSharp drawing inside a ReactorUI component.\
Let's first install ReactorUI SkiaSharp binding package:

```
Install-Package XamarinReactorUI.Skia
```

`XamarinReactorUI.Skia` package provides two classes: `RxSKCanvasView` and `RxSKGLView`. They can be used to integrate SkiaSharp backends in a component.

Let's create a sample empty page:

```csharp
public class MainPage : RxComponent
{
    public override VisualNode Render()
    {
        return new RxContentPage()
        {
        };
    }
}
```

To draw some graphics we just need to create a `RxSKCanvasView` and handle the `OnPaintSurface`callback (sample drawing code is freely copied from Xamarin doc):

```csharp
    public class MainPageState : IState
    { 
        public double RotationAngle { get; set; }
    }

    public class MainPage : RxComponent<MainPageState>
    {
        public override VisualNode Render()
        {
            return new RxContentPage()
            {
                new RxSKCanvasView()
                    .OnPaintSurface(OnPaintCanvasSurface)
            };
        }

        private void OnPaintCanvasSurface(SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;

            canvas.Clear();

            string text = "OUTLINE";

            // Create an SKPaint object to display the text
            SKPaint textPaint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeWidth = 1,
                FakeBoldText = true,
                Color = SKColors.Blue
            };

            // Adjust TextSize property so text is 95% of screen width
            float textWidth = textPaint.MeasureText(text);
            textPaint.TextSize = 0.95f * info.Width * textPaint.TextSize / textWidth;

            // Find the text bounds
            SKRect textBounds = new SKRect();
            textPaint.MeasureText(text, ref textBounds);

            // Calculate offsets to center the text on the screen
            float xText = info.Width / 2 - textBounds.MidX;
            float yText = info.Height / 2 - textBounds.MidY;

            // And draw the text
            canvas.DrawText(text, xText, yText, textPaint);
        }
    }
```

If you run the app you should something like this:

![Initial app version](/files/-M5WIqz-nFlgt2uYhn3c)

Now let's add some interactivity: for example adding the ability to rotate the text. We need a state that hold the current rotation angle, a slider to allow user modify this value, finally we need to invalidate SkiaSharp canvas when angle changes:

```csharp
    public class MainPageState : IState
    { 
        public double RotationAngle { get; set; }
    }

    public class MainPage : RxComponent<MainPageState>
    {
        private SKCanvasView _canvasView;

        public override VisualNode Render()
        {
            return new RxContentPage()
            {
                new RxStackLayout()
                {
                    new RxLabel("Rotation Angle"),
                    new RxSlider()
                        .Minimum(0)
                        .Maximum(360.0)
                        .Value(State.RotationAngle)
                        .OnValueChanged(v => SetState(s =>
                        {
                            s.RotationAngle = v.NewValue;
                            _canvasView.InvalidateSurface();
                        }))
                        .HFill()
                        .VStart(),
                    new RxSKCanvasView(canvasView => _canvasView = canvasView)
                        .OnPaintSurface(OnPaintCanvasSurface)
                        .VFillAndExpand()
                }
            };
        }

        private void OnPaintCanvasSurface(SKPaintSurfaceEventArgs args)
        {
            .... omitted for brevity ....

            // And draw the text
            canvas.RotateDegrees((float)State.RotationAngle, info.Width / 2, info.Height / 2);
            canvas.DrawText(text, xText, yText, textPaint);
        }
    }
```

Following is the app as it should work now:

![ReactorUI+SkiaSharp demo app](/files/-M5WKoiQSxTi1mO1_2DN)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://adospace.gitbook.io/reactorui/sample-with-skiasharp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
