WPF Canvas.Left / Canvas.Top - not quite the right coordinates when turning, why?

I have a strange but big problem. I am trying to allow the user to move / rotate some rectangles on the canvas. I base my mechanism on managing Canvas.Left / Canvas.Top properties for moving and RenderTransform.Rotate for rotating. I only need rotation at angles 0/90/180/270.

The problem is that the rectangle, which is placed at the coordinates 0.0 when the angle 0 is rotated, shows ok, but the same rectangle, equal to 0.0 when the 90-degree rotation, shows the element in other coordinates than 0,0. As I can see, the coordinates are always correct in the case where the rotation is 0 or 180, but incorrect in the case of 90/270. The difference between what coordinates are set and what the user sees is related to the difference between height and width.

Has anyone encountered such a problem before?

Thanks Daniel

edit:

Of course, here are a few haml:

<Canvas Height="500" Width="500" Background="Green" <Rectangle Canvas.Left="0" Canvas.Top="0" Height="50" Width="100" RenderTransformOrigin="0.5,0.5" Fill="Red" <Rectangle.RenderTransform> <RotateTransform Angle="90" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="0" Canvas.Top="0" Height="50" Width="100" RenderTransformOrigin="0.5,0.5" Fill="RoyalBlue" <Rectangle.RenderTransform> <RotateTransform Angle="0" /> </Rectangle.RenderTransform> </Rectangle> </Canvas> </Grid> 

as you can see, the blue rectangle seems to be correctly placed (0,0), but the red one is displayed in different coordinates, even if it returns stil 0,0.

I found that the formula:

displayPointX = Canvas.Left + height / 2 - width / 2

diaplayPointY = Canvas.Top + height / 2 - width / 2

+4
source share
3 answers

The behavior you describe occurs under the following conditions:

  • Your canvas is not rectangular,
  • You have a RenderTransformOrigin of "0.5.0.5" and
  • You are using RotateTransform for your RenderTransform

The reason you see this is because a rectangle rotated 180 degrees around its center has exactly the same borders, but a rectangle rotated 90 or 270 degrees does not. Draw a wide but skinny rectangle that rotates and you can easily see that it is.

When you rotate 90 or 270 degrees, your corners no longer match the container.

Many solutions are available:

  • Make the container level.
  • Resize your canvas (flip width and height) to 90 and 270 rpm
  • Combine ScaleTransform with your RotateTransform, which scales the canvas w / h in one direction and h / w when rotated 90 or 270 degrees so that the canvas stretches to fit the new rectangle.
  • Add a TranslateTransform to your RotateTransform, which shifts the coordinate system by wh and hw when the rotation is 90 or 270 degrees.
  • Calculate the new RenderTransformOrigin to make the angle where you want.
+2
source

Daniel, everything you say is correct. If you have a rectangle and you set the origin to 0.5, 0.5, it means "rotate around the center of gravity of this object," so if you rotate 90 or 270 degrees, of course, it will look exactly the same as you see .

If you want the rectangle to rotate 90 degrees and still be in the upper left corner, you either need to rotate 90 and then translate to X and Y so that the angle coincides with 0.0, or you need to rotate around another center (e.g. , 0,0) and translate only into X.

Here is an example:

 <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Canvas Height="500" Width="500" Background="Green"> <Rectangle Canvas.Left="0" Canvas.Top="0" Height="50" Width="100" RenderTransformOrigin="0.5,0.5" Fill="Red"> <Rectangle.RenderTransform> <TransformGroup> <RotateTransform Angle="90" /> <TranslateTransform X="-25" Y="25" /> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="0" Canvas.Top="0" Height="50" Width="100" RenderTransformOrigin="0.5,0.5" Fill="RoyalBlue"> <Rectangle.RenderTransform> <RotateTransform Angle="0" /> </Rectangle.RenderTransform> </Rectangle> </Canvas> </Page> 

Perhaps it would be better if you explained what you were actually trying to do with it. It is also strange that you say that 0 and 180 are large, because the angle corresponds to 0.0, but then your figure rotates, and we don’t know if maintaining orientation is important to you or not.

+3
source

The reason for the coordinate change is that the canvas coordinate system rotates with the canvas.

http://msdn.microsoft.com/en-us/library/system.windows.media.rotatetransform.aspx :

When you use RotateTransform, realize that the transformation rotates the coordinate system for a specific object about a point (0, 0).

Assuming you are spinning around the centroid of the square when you rotate 90 degrees (clockwise, the RotateTransform considers positive), (0,0) refers to the upper right corner of the screen, for 180 this refers to the lower right corner, for 270 it refers to the lower left corner, and at 0 it, as expected, refers to the upper left corner.

+1
source

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


All Articles