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>
- Не использовать
Margin
для этого вида позиционирования используйте прилагаемыйCanvas
свойства, т.е.Canvas.Left
, так далее. - Вы также можете использовать
TransformGroup
и применитьTranslateTransform
иRotateTransform
Предположительно, вращение должно быть сделано до перевода.