You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:05:59