How can you calculate the X / Y coordinate for scaling

I am writing a WPF application with the ability to scale and pan, but what I want to implement is the ability to scale and pan “automatically” (with the click of a button).

I have all the methods defined for zooming and panning, but I am having problems informing the application about the desired X / Y coordinates for panning.

Basically, I know that I want the control to be centered with the desired zoom level (for example, increased by 6 times), but the pan destination is NOT the center point of the control, because after scaling it is scaled.

Does anyone know a way to calculate the desired X / Y position for panning, also considering scaling? Am I just scaling the desired destination? This does not seem to work for me ...

thanks a lot

EDIT - COMPLETED -

Here is what I have that works fine :)

<Canvas x:Name="LayoutRoot" Background="{DynamicResource WindowBackground}" Width="1024" Height="768"> <Canvas x:Name="ProductCanvas" Width="1024" Height="768"> <Canvas.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform /> </TransformGroup> </Canvas.RenderTransform> <Rectangle x:Name="r1" Fill="White" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="121.5" MouseDown="r1_MouseDown"/> <Rectangle x:Name="r2" Fill="#FF942222" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="121.5" MouseDown="r2_MouseDown"/> <Rectangle x:Name="r3" Fill="#FF2B1E9F" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="408" MouseDown="r3_MouseDown"/> <Rectangle x:Name="r4" Fill="#FF1F6E1D" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="408" MouseDown="r4_MouseDown"/> </Canvas> </Canvas> 

---- ---- FROM#

  private void r1_MouseDown(object sender, MouseButtonEventArgs e1) { Rect bounds = r1.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r1.ActualWidth, r1.ActualHeight)); ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2))); } private void r2_MouseDown(object sender, MouseButtonEventArgs e1) { Rect bounds = r2.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r2.ActualWidth, r2.ActualHeight)); ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2))); } private void r3_MouseDown(object sender, MouseButtonEventArgs e1) { Rect bounds = r3.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r3.ActualWidth, r3.ActualHeight)); ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width / 2), bounds.TopLeft.Y + (bounds.Height / 2))); } private void r4_MouseDown(object sender, MouseButtonEventArgs e1) { Rect bounds = r4.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r4.ActualWidth, r4.ActualHeight)); ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2))); } public void ZoomInAndPan(double zoomTo, Point translateTarget) { var group = (ProductCanvas.RenderTransform as TransformGroup); var zoomTransform = group.Children[0] as ScaleTransform; var translateTransform = group.Children[3] as TranslateTransform; Point center = new Point(512, 384); destinationPoint.X *= newScale; destinationPoint.Y *= newScale; var deltaX = center.X - (translateTarget.X); var deltaY = center.Y - (translateTarget.Y); translateTransform.BeginAnimation(TranslateTransform.XProperty, CreateZoomAnimation(deltaX)); translateTransform.BeginAnimation(TranslateTransform.YProperty, CreateZoomAnimation(deltaY)); zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, CreateZoomAnimation(zoomTo)); zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, CreateZoomAnimation(zoomTo)); } private DoubleAnimation CreateZoomAnimation(double toValue) { var da = new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(700))) { AccelerationRatio = 0.1, DecelerationRatio = 0.9 }; return da; } 
+4
source share
2 answers

You are talking about transformation - pan and scale.

You can do this in several different ways, but since you are using WPF, is there a reason why you cannot just use RenderTransforms?

 var pointClicked = (where user clicked) var myWindow = (whatever your window is); myWindow.RenderTransform = new TransformGroup(); var pan = new TranslateTransform(pointClicked.X, pointClicked.Y); var scale = new ScaleTransform(6.0,6.0); myWindow.RenderTransform.Children.Add(pan); myWindow.RenderTransform.Children.Add(scale); 

If you don’t want to go along this route, you need to do the 2D transformation “manually”: first make a panorama, then zoom. Transformations are usually not common; you will get the wrong results if you do them in a different order.

+5
source

Initially, your viewport is at (0,0), and the image and viewport are sized X by Y. You want to scale the size using some magnification factor m so that your images are sized mX by mY, but your viewport (the part that you show) is still a rectangle of size X by Y, located at (0,0) in the image. Therefore, you need to move the view port.

If your image is now mX by mY, you can find the midpoints by dividing them in two. You can then subtract half the size of the viewport to get the top left corner. Something like (mX / 2 - X / 2, mY / 2 - Y / 2).

+1
source

Source: https://habr.com/ru/post/1303055/


All Articles