Reputation: 31
I am trying to convert the mouse click coordinates to canvas coordinates. The canvas can be dynamically scaled. I implemented a zoom feature that ScaleTransforms the entire canvas. The canvas itself has one image that serves as a background for the window. When the user uses the mouse wheel, the background zooms in and out. How do I convert the mouse click coordinates to reflect the scaled position on the image?
Scaling the Map Image code:
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
double zoom = 1.1;
scaleTransform.CenterX = this.Width / 2;
scaleTransform.CenterY = this.Height / 2;
if (e.Delta > 0)
{
scaleTransform.ScaleX *= zoom;
scaleTransform.ScaleY *= zoom;
}
else
{
scaleTransform.ScaleX /= zoom;
scaleTransform.ScaleY /= zoom;
}
// Zoom out limits
if(scaleTransform.ScaleX <= 1) { scaleTransform.ScaleX = 1; }
if(scaleTransform.ScaleY <= 1) { scaleTransform.ScaleY = 1; }
// Zoom in limits
if(scaleTransform.ScaleX >= 2.4) { scaleTransform.ScaleX = 2.4; }
if(scaleTransform.ScaleY >= 2.4) { scaleTransform.ScaleY = 2.4; }
}
Add icon to the map image:
private void mapImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var v = e.GetPosition(this);
var temp = GetImage("Assets/icon.png");
Canvas.SetLeft(temp, v.X);
Canvas.SetTop(temp, v.Y);
temp.Width = 32;
temp.Height = 32;
temp.RenderTransform = new ScaleTransform(0.5, 0.5, temp.Width / 2, temp.Height / 2);
mainCanvas.Children.Add(temp);
}
I'm basically trying to add a new icon image to the map with the left mouse button. However if the map is zoomed in while i'm trying to add an icon, the position of the image doesn't correlate to the position of the map where you clicked. It goes off to some place far from where the mouse cursor is. How do I convert the coordinates based on the scale of the map image?
Note: if i don't zoom in at all (the scale of the image is 1), then the icons are placed exactly where I click.
Upvotes: 0
Views: 3524
Reputation: 3031
The simplest way is to get the original image size, then look at the WPF Image Control's (or whatever other control you're using) actual width, and get the scale between them
var eventLocation = e.GetPosition(MainImage);
var scaleRatio = SourceBitmap.Width / YourWpfImageControlName.ActualWidth;
var realX = eventLocation.X * scaleRatio;
var realY = eventLocation.Y * scaleRatio;
This assumes you use uniform scaling (eg the aspect ratio is maintained), but you can do the same ratio calculation for both the X and Y axes independently by doing the same calculation for height and applying it to the Y value
Upvotes: 0
Reputation: 3556
I guess the parameter "this" to e.GetPosition method makes the trouble. You need to get the relative position from the Canvas but not from the Window. The parameter should be the Canvas "mainCanvas". So, the latter method would be like:
private void mainCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var v = e.GetPosition(mainCanvas);
var temp = new Image
{
Source = new BitmapImage(new Uri("Assets/icon.png", UriKind.Relative)),
Width = 32,
Height = 32
};
Canvas.SetLeft(temp, v.X - temp.Width / 2);
Canvas.SetTop(temp, v.Y - temp.Height / 2);
mainCanvas.Children.Add(temp);
}
Upvotes: 2