First let me state, this is my first time messing with any type of drawing utility and I am way outside of my wheelhouse. First I will describe the issue I am having, then what I am trying to do and then my code.
Issue:
After scaling and transforming the canvas, when I touch the canvas on the device screen, then break on the 'location' point in the touch event, its not the same location that the canvas drew something. I need the exact location I drew something to show the user a popup.
What I am trying to do:
I have an image that I scale and draw to the canvas. Then I draw a large red rectangle on the image and smaller rectangles inside the larger rectangle. When the user presses the zoom button I scale by an increasing factor giving the allusion that we are zooming in on the center. So essentially the image grows in size, the large rectangle grows in size and the little rectangles grow in size. This seems to work flawlessly...but I feel I have done something wrong being that when I touch one of the little rectangles, the location is not the same (x,y) it was drawn at.
I thought it may have something to do with canvas.ResetMatrix() or canvas.Save() or canvas.Restore() but none of those seem to work so I am absolutely baffled. Again any help with this endeavor would but much appreciated.
public static void DrawLayout(SKImageInfo info, SKCanvas canvas, SKSvg svg, SetupViewModel vm)
var layout = vm.SelectedReticleLayout;
float yRatio;
float xRatio;
float widgetHeight = 75;
float widgetWidth = 170;
float availableWidth = 720;
float availableHeight = 1280;
var currentZoomScale = getScale();
canvas.Translate(info.Width / 2f, info.Height / 2f);
SKRect bounds = svg.ViewBox;
xRatio = (info.Width / bounds.Width) + ((info.Width / bounds.Width) * currentZoomScale);
yRatio = (info.Height / bounds.Height) + ((info.Height / bounds.Height) * currentZoomScale);
float ratio = Math.Min(xRatio, yRatio);
canvas.Scale(ratio);
canvas.Translate(-bounds.MidX, -bounds.MidY);
canvas.DrawPicture(svg.Picture, new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Fill });
// now set the X,Y and Width and Height of the large Red Rectangle
float imageCenter = canvas.LocalClipBounds.Width / 2;
layout.RedBorderXOffSet = imageCenter - (imageCenter / 2.0f) + canvas.LocalClipBounds.Left;
float redBorderYOffSet = (float)(svg.Picture.CullRect.Top + Math.Ceiling(.0654450261780105f * svg.Picture.CullRect.Bottom));
layout.RedBorderYOffSet = (float)(canvas.LocalClipBounds.Top + Math.Ceiling(.0654450261780105f * canvas.LocalClipBounds.Bottom));
layout.RedBorderWidth = canvas.LocalClipBounds.Width / 2.0f;
layout.RedBorderWidthXOffSet = layout.RedBorderWidth + layout.RedBorderXOffSet;
layout.RedBorderHeight = (float)(canvas.LocalClipBounds.Bottom - Math.Ceiling(.0654450261780105f * canvas.LocalClipBounds.Bottom * 2)) - canvas.LocalClipBounds.Top;
layout.RedBorderHeightYOffSet = layout.RedBorderYOffSet + layout.RedBorderHeight;
// draw the large red rectangle
canvas.DrawRect(layout.RedBorderXOffSet, layout.RedBorderYOffSet, layout.RedBorderWidth, layout.RedBorderHeight, RedBorderPaint);
// clear the tracked widgets, tracked widgets are updated every time we draw the widgets
// base widgets contain the default size and location relative to the scope. base line widgets
// will need to be multiplied by the node scale height and width
layout.TrackedWidgets.Clear();
var widget = new widget
{
X = layout.RedBorderXOffSet + 5;
Y = layout.RedBorderYOffSet + layout.TrackedReticleWidgets[0].Height + 15;
Height = layout.RedBorderHeight * (widgetHeight / availableHeight);
Width = layout.RedBorderWdith * (widgetWidth / availableWidth);
}
// define colors for text and border colors for small rectangles (widgets)
public static SKPaint SelectedWidgetColor => new SKPaint { Color = SKColors.LightPink, Style = SKPaintStyle.StrokeAndFill, StrokeWidth = 3 };
public static SKPaint EmptyWidgetBorder => new SKPaint { Color = SKColors.DarkGray, Style = SKPaintStyle.Stroke, StrokeWidth = 3 };
public static SKPaint EmptyWidgetText => new SKPaint { Color = SKColors.Black, TextSize = 10, FakeBoldText = false, Style = SKPaintStyle.Stroke, Typeface = SKTypeface.FromFamilyName("Arial") };
public static SKPaint DefinedWidgetText => new SKPaint { Color = SKColors.DarkRed, FakeBoldText = false, Style = SKPaintStyle.Stroke };
// create small rectangle (widget) and draw the widget
var widgetRectangle = SKRect.Create(widget.X, widget.Y, widget.Width, widget.Height);
canvas.DrawRect(widgetRectangle, widget.IsSelected ? SelectedWidgetColor : EmptyWidgetBorder);
// now lets create the text to draw in the widget
string text = EnumUtility.GetDescription(widget.WidgetDataType);
float textWidth = EmptyWidgetText.MeasureText(text);
EmptyWidgetText.TextSize = widget.Width * GetUnscaledWidgetWith(widget) * EmptyWidgetText.TextSize / textWidth;
SKRect textBounds = new SKRect();
EmptyWidgetText.MeasureText(text, ref textBounds);
float xText = widgetRectangle.MidX - textBounds.MidX;
float yText = widgetRectangle.MidY - textBounds.MidY;
canvas.DrawText(text, xText, yText, EmptyWidgetText);