如何在C#的WPF TransformGroup中为特定变换使用相对坐标
WPF中TransformGroup内指定单个变换相对原点的问题
根据微软知识库文档,当给UIElement的RenderTransform属性应用Transform时,可通过RenderTransformOrigin为应用到元素的每个Transform指定原点。我希望在TransformGroup中实现多次旋转,每次围绕各自的中心点(比如元素中心相对坐标(0.5,0.5)),但找不到为单个变换定义RenderTransformOrigin的方法。于是尝试设置对象的RenderTransformOrigin,假设未指定CenterX/CenterY的RotateTransform会使用该相对坐标,但测试后发现这个假设不成立。
测试代码
MainWindow.xaml
<Window x:Class="RenderTransformOrigin.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:RenderTransformOrigin" mc:Ignorable="d" Title="MainWindow" Height="540" Width="500"> <StackPanel> <Canvas x:Name="cv" Height="500" Width="500"/> </StackPanel> </Window>
MainWindow.xaml.cs
using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace RenderTransformOrigin { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TextBlock tblock = new TextBlock() { Text = "A", FontSize = 30, FontWeight = FontWeights.Bold }; tblock.Measure(new Size()); tblock.Arrange(new Rect()); cv.Measure(new Size()); cv.Arrange(new Rect()); tblock.RenderTransformOrigin = new Point(0.5, 0.5); TransformGroup tgroup = new TransformGroup(); tgroup.Children.Add(new TranslateTransform() { X = (cv.ActualWidth - tblock.ActualWidth) / 2, Y = (cv.ActualHeight - tblock.ActualHeight) / 2 - 100 }); tgroup.Children.Add(new RotateTransform() { Angle = 90, CenterX = (cv.ActualWidth - tblock.ActualWidth) / 2 , CenterY = (cv.ActualHeight - tblock.ActualHeight) / 2 }); //tgroup.Children.Add(new RotateTransform() { Angle = -90 }); tblock.RenderTransform = tgroup; cv.Children.Add(tblock); } } }
这段代码将TextBlock放置在Canvas的X轴居中、Y轴略偏上位置,先将文本旋转90度,期望再围绕元素中心旋转使其恢复正向。但取消注释第二个RotateTransform后,文本会绕Canvas原点(0,0)旋转导致移出屏幕,即使添加CenterX=0.5,CenterY=0.5也没有效果。
核心问题
在TransformGroup包含其他不同中心的变换且需保留其效果的前提下,如何为特定变换使用相对坐标?
解决方法(7月21日,Clemens回复后)
通过先设置以元素中心为RotateTransform的CenterX/CenterY且Angle为0,添加平移和绕Canvas中心的旋转,再修改第一个RotateTransform的Angle,实现了需求,代码如下:
public MainWindow() { InitializeComponent(); TextBlock tblock = new TextBlock() { Text = "A", FontSize = 30, FontWeight = FontWeights.Bold }; tblock.Measure(new Size()); tblock.Arrange(new Rect()); cv.Measure(new Size()); cv.Arrange(new Rect()); double cx = (cv.ActualWidth - tblock.ActualWidth) / 2, cy = (cv.ActualHeight - tblock.ActualHeight) / 2; TransformGroup tgroup = new TransformGroup(); tgroup.Children.Add(new RotateTransform() { Angle = 0, CenterX = tblock.ActualWidth / 2, CenterY = tblock.ActualHeight / 2 }); tgroup.Children.Add(new TranslateTransform() { X = cx, Y = cy - 100 }); tgroup.Children.Add(new RotateTransform() { Angle = 90, CenterX = cx , CenterY = cy }); tblock.RenderTransform = tgroup; cv.Children.Add(tblock); ((RotateTransform)((TransformGroup)(tblock).RenderTransform).Children[0]).Angle = -90; }
此时文本先绕Canvas中心旋转90度后,再绕自身中心旋转-90度恢复正向。
内容的提问来源于stack exchange,提问作者JayY
相关产品推荐
相关产品推荐

