RotateTransform сдвигает мое изображение, а также поворачивает его

Итак, у меня есть объект Image, который я хочу вращать вокруг своего верхнего левого угла. Я устанавливаю RotateTransform 'X' градусов. Мое изображение имеет установленное поле (400 400,0,0). Это центрирует это на холсте.

Проблема в том, что когда я применяю разные углы поворота, изображение смещается вправо и вниз. Глядя на посты, я теперь понимаю, ПОЧЕМУ это происходит. Преобразование поворота определяет ограничивающий прямоугольник, поэтому если вы поворачиваете изображение, оно будет иметь больший ограничивающий прямоугольник. Маржа применяется к этому ограничивающему прямоугольнику, что приводит к смещению фактического изображения вниз и вправо при изменении угла.

Я хочу, чтобы верхний левый угол изображения всегда был точно (400 400) на моем холсте, а изображение вращалось вокруг этой точки.

Я сделал некоторые вычисления и могу заставить его вести себя, сдвигая левое и верхнее поле, но могу получить правильные вычисления только в квадранте 1 и 4 (0-90 градусов) и (270-360 градусов), используя следующие уравнения:

Для 0-90 градусов: (просто нужно изменить верхнюю часть поля. Желаемое поле равно (400 400,0,0) Margin=(400-sin(угол)*Image.Height, 400, 0, 0);

Для 270-360 градусов: (просто нужно изменить верхнюю часть поля. Желаемое поле равно (400 400,0,0) Margin=(400, 400 + sin(угол)*Image.Width, 0, 0);

Я экспериментировал с использованием RotateTransform.Transform(точка) и Image.TranslatPoint(точка), но не могу заставить их работать.

У кого-нибудь есть предложения для меня?

Я думаю, если бы я мог выяснить, каким был прямоугольник привязки изображения в любой момент времени, я мог бы выяснить разницу между его шириной / высотой и шириной / высотой моего изображения и использовать это для соответствующего смещения поля.

Я собрал небольшое приложение, которое покажет мою проблему. При запуске приложение показывает красную точку, где я хочу, чтобы верхний левый угол прямоугольника был. Я упростил его, чтобы использовать сетку вместо изображения. В левом верхнем углу экрана есть текстовое поле, в котором вы можете указать угол поворота. Справа от текстового поля расположены две кнопки RepeatButton, которые будут увеличивать и уменьшать угол, если просто щелкнуть и удерживать их. Обратите внимание, как при изменении угла верхний левый угол сетки смещается от красной точки. Я хочу, чтобы он действовал так, как будто вы поместили булавку в верхний левый угол и повернули ее вокруг булавки без смещения от точки, с которой начинается угол.

Спасибо за вашу помощь.

Вот код для примера приложения:

XAML:

<Window x:Class="RenderTransformTester.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="900" Width="900">
    <Canvas x:Name="_canvas">
        <Grid x:Name="_gridImage"  Width="400" Height="200" Canvas.Left="400" Canvas.Top="400" Background="Navy">
            <Grid.LayoutTransform>
                <RotateTransform Angle="45" CenterX="0" CenterY="0"/>
            </Grid.LayoutTransform>
        </Grid>
        <Ellipse Fill="Red" Width="20" Height="20" Margin="390,390,0,0"/>
        <TextBox x:Name="_textBoxAngle" Width="70" Height="30" TextChanged="_textBoxAngle_TextChanged" Text="0"/>
        <RepeatButton x:Name="_buttonUp" Width="30" Height="15" Margin="70,0,0,0" Click="_buttonUp_Click"/>
        <RepeatButton x:Name="_buttonDown" Width="30" Height="15" Margin="70,15,0,0" Click="_buttonDown_Click"/>
    </Canvas>
</Window>

CodeBehind:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace RenderTransformTester
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        static double _left = -1;
        static double _top = -1;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void _textBoxAngle_TextChanged(object sender, TextChangedEventArgs e)
        {
            int angle;
            int.TryParse(_textBoxAngle.Text, out angle);
            angle += 720;
            angle %= 360;

            _gridImage.LayoutTransform = new RotateTransform(angle, 0, 0);
        }

        private void _buttonUp_Click(object sender, RoutedEventArgs e)
        {
            int angle;
            int.TryParse(_textBoxAngle.Text, out angle);
            angle++;
            angle = angle % 360;
            _textBoxAngle.Text = angle.ToString();
        }

        private void _buttonDown_Click(object sender, RoutedEventArgs e)
        {
            int angle;
            int.TryParse(_textBoxAngle.Text, out angle);
            angle--;
            angle = angle % 360;
            _textBoxAngle.Text = angle.ToString();
        }

        private static double RadiansToDegrees(double radians)
        {
            return radians * 180 / Math.PI;
        }

        private static double DegreesToRadians(double degrees)
        {
            return degrees * Math.PI / 180;
        }
    }
}

2 ответа

Решение

Вы хотите TranslateTransform в TransformGroup

<Grid>
    <Grid.RenderTransform>
        <TransformGroup>
            <RotateTransform Angle="45" CenterX="0" CenterY="0" />
            <TranslateTransform X="400" Y="400" />
        </TransformGroup>
    </Grid.RenderTransform>
</Grid>
  1. Не использовать Margin для этого вида позиционирования используйте прилагаемый Canvas свойства, т.е. Canvas.Left, так далее.
  2. Вы также можете использовать TransformGroup и применить TranslateTransform и RotateTransform Предположительно, вращение должно быть сделано до перевода.
Другие вопросы по тегам