WPF Canvas.Left / Canvas.Top не совсем правильные координаты при повороте, почему? - PullRequest
4 голосов
/ 12 февраля 2010

У меня странная, но большая проблема. Я пытаюсь позволить пользователю перемещать / вращать некоторые прямоугольники на холсте. Я основываю свой механизм на манипулировании свойствами Canvas.Left / Canvas.Top для перемещения и RenderTransform.Rotate для вращения. Мне нужно вращение только на углы 0/90/180/270.

Проблема в том, что прямоугольник, который расположен в координатах 0.0 на повороте на 0 градусов, показывает нормально, но тот же прямоугольник на 0.0 с поворотом на 90 показывает элемент в координатах, отличных от 0.0. Как я вижу, координаты всегда правильные в случае вращения 0 или 180, но неправильные в случае 90/270. Разница между заданными координатами и тем, что видит пользователь, связана с разницей между высотой и шириной.

Кто-нибудь сталкивался с такой проблемой раньше?

Спасибо, Даниэл

редактирование:

Конечно, вот какой-то 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>
                <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>

Как вы можете видеть, синий прямоугольник кажется правильно размещенным (0,0), а красный - в разных координатах, даже если он возвращает стиль 0,0.

Я обнаружил, что Формула:

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

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

Ответы [ 3 ]

3 голосов
/ 12 февраля 2010

Даниэль, все, что тебе говорят, правильно. Если у вас есть Прямоугольник, и вы установили начало координат на 0,5, 0,5, это означает «вращаться вокруг центроида этого объекта», поэтому, если вы поверните на 90 или 270 градусов, конечно, это будет выглядеть точно так же, как вы видите.

Если вы хотите, чтобы прямоугольник повернулся на 90 градусов и все же оказался в верхнем левом углу, вам нужно либо повернуть на 90, а затем перевести в X и Y, чтобы угол совпадал с 0,0, или вам нужно вращаться вокруг другого центра (например, 0,0) и переводить только в X.

Вот пример:

<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>

Возможно, было бы лучше, если бы вы объяснили, что вы действительно пытаетесь сделать с этим. Также странно, что вы говорите, что 0 и 180 - это здорово, потому что угол совпадает с 0,0, но тогда ваша фигура поворачивается, и мы не знаем, важно ли для вас сохранение ориентации.

2 голосов
/ 12 февраля 2010

Поведение, которое вы описываете, происходит при следующих условиях:

  1. Ваш холст не прямоугольный,
  2. У вас есть RenderTransformOrigin "0.5,0.5" и
  3. Вы используете RotateTransform для вашего RenderTransform

Причина, по которой вы это видите, в том, что прямоугольник, повернутый на 180 градусов вокруг своего центра, имеет точно такие же границы, а прямоугольник, повернутый на 90 или 270 градусов, - нет. Изобразите широкий, но тонкий прямоугольник, вращающийся Вы легко можете видеть, что это так.

Когда вы поворачиваете на 90 или 270 градусов, ваши углы больше не совпадают с контейнером.

Доступны многие решения:

  • Сделать контейнер точно квадратным
  • Измените размер вашего холста (измените ширину и высоту) на 90 и 270 поворотов
  • Объедините ScaleTransform с вашим RotateTransform, который масштабирует холст на w / h в одном направлении и h / w всякий раз, когда вращение составляет 90 или 270 градусов, чтобы холст растягивался, чтобы соответствовать новому прямоугольнику
  • Добавить TranslateTransform к вашему RotateTransform, который сдвигает систему координат на w-h и h-w всякий раз, когда поворот на 90 или 270 градусов
  • Рассчитайте новый RenderTransformOrigin, чтобы угол получился там, где вам нужно
1 голос
/ 12 февраля 2010

Причина, по которой координаты меняются, заключается в том, что система координат холста вращается вместе с холстом.

http://msdn.microsoft.com/en-us/library/system.windows.media.rotatetransform.aspx состояния:

Когда вы используете RotateTransform, понять, что преобразование вращает систему координат для конкретный объект о точке (0, 0).

Предполагается, что вы вращаетесь вокруг центроида квадрата, когда вы поворачиваетесь на 90 градусов (по часовой стрелке направление RotateTransform считает положительным), (0,0) относится к верхнему правому углу экрана, для 180 это относится в правом нижнем углу, для 270 это относится к нижнему левому углу, а в 0 это, как ожидается, относится к верхнему левому углу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...