Search code examples
xamarinmatrixskiaskiasharp

Translate matrix to center and fit a rectangle


I use SkiaSharp to draw some SKRect on a SKCanvas. I'm trying to implement a "scale to fit and center" functionality for the drawing area. I used the following code to calculate the bounding box for all the SKRects.

private SKRect GetBoundingBox()
{
    int xMin = AllRectangles.Min(s => (int)s.Left);
    int yMin = AllRectangles.Min(s => (int)s.Top);
    int xMax = AllRectangles.Max(s => (int)s.Right);
    int yMax = AllRectangles.Max(s => (int)s.Bottom);
    SKRect result = new SKRect(xMin, yMin, xMax, yMax);
    return result;
}

Now I want to translate the SKMatrix used during PaintSurface to center the bounding box (with all the items in it) and scale the bounding box to fit the SKCanvasView. I have a GIF which shows the Navigator View in Photoshop, doing what I'm trying to build. Navigator


Solution

  • I finally found the solution to my problem, and I wanted to share my code in order help others that might struggle with a similar issue. The following method caluclates the scale for the matrix in order to fit the viewport. Both, the scale factor and a translation of the viewport rectangle are applied to the matrix. After this operations a redraw of the canvas is needed.

    public void CenterAndFitRectangle(SKRect viewport)
    {
        var viewPortRectangle = _currentMatrix.MapRect(viewport);
        var scale = Math.Min(CanvasView.Bounds.Width / viewPortRectangle.Width, CanvasView.Bounds.Height / viewPortRectangle.Height);
        _currentMatrix.ScaleX = scale;
        _currentMatrix.ScaleY = scale;
        _currentMatrix.TransX = -viewPortRectangle.Left * scale;
        _currentMatrix.TransY = -viewPortRectangle.Top * scale;
    }