Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 旋转变换与平移变换的结合_C#_Wpf_Transform_Rotatetransform - Fatal编程技术网

C# 旋转变换与平移变换的结合

C# 旋转变换与平移变换的结合,c#,wpf,transform,rotatetransform,C#,Wpf,Transform,Rotatetransform,我使用Thumb类让用户在画布上拖放图像。当按下右键时,我希望用户能够旋转图像。旋转以图像中心为基础。我有以下XAML代码 <Grid> <Canvas Background="Red" Grid.RowSpan="2" x:Name="canvas" PreviewMouseRightButtonUp="Canvas_MouseUp" PreviewMouseMove="Canvas_MouseMove">

我使用Thumb类让用户在画布上拖放图像。当按下右键时,我希望用户能够旋转图像。旋转以图像中心为基础。我有以下XAML代码

<Grid>

    <Canvas Background="Red" Grid.RowSpan="2" x:Name="canvas" 
        PreviewMouseRightButtonUp="Canvas_MouseUp" 
        PreviewMouseMove="Canvas_MouseMove">

        <UserControl MouseRightButtonDown="Canvas_MouseDown" RenderTransformOrigin="0.5,0.5">

            <Thumb Name="myRoot" DragDelta="myRoot_DragDelta">
                <Thumb.Template>
                    <ControlTemplate>
                        <Grid>

                            <Image Source="/WpfApplication1;component/someImage.png" />

                            <Rectangle Stroke="#FF0061CE" StrokeThickness="1" Width="230" Height="250" />

                        </Grid>
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>

            <UserControl.RenderTransform>
                <TransformGroup>
                    <RotateTransform x:Name="rotateTransform" />
                    <TranslateTransform x:Name="translateTransform" />
                </TransformGroup>
            </UserControl.RenderTransform>
        </UserControl>

    </Canvas>

</Grid>

如果我只在屏幕周围拖放图像,并稍微旋转图像(在任何方向上50度似乎都可以),它就会工作。然而,如果对其进行更多的操作,图像就会在屏幕上不可预测地移动

我尝试将转换移动到不同的控件,以避免混淆它们,但没有收到可接受的结果

我怎样才能让我的代码表现得像我想要的那样

更新:这让我发疯。我已经更改了代码和XAML,改为使用MatrixTransformation

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (!isMouseDown) return;

        var curPos = Mouse.GetPosition(canvas);

        angle = (lastAngle + (pos.Y - curPos.Y)) % 360;

        UpdateMatrixTransform();
    }

    private void myRoot_DragDelta(object sender, DragDeltaEventArgs e)
    {
        posX += e.HorizontalChange;
        posY += e.VerticalChange;  

        UpdateMatrixTransform();
    }

    void UpdateMatrixTransform()
    {
        Matrix m = new Matrix();


        m.Rotate(angle);

        m.OffsetX = posX;
        m.OffsetY = posY;

        matrixT.Matrix = m;
    }

在我看来,这应该是可行的:首先,旋转图形,然后将其移动到偏移位置。它不像我期望的那样工作。它旋转图像,但如果我继续移动鼠标,它会以螺旋的方式奇怪地向外移动。无论我做什么,以什么顺序执行转换,它都不会工作

您必须告诉RotateTransform您要围绕对象的中心而不是坐标系的中心旋转,这是默认设置。为此,请将RotateTransform的CenterX和CenterY属性设置为对象的中心。

我不确定为什么要使用UserControl来包裹Thumb,因为它应该可以充当此处的根元素。下面是一个解决方案,它包括放弃使用TranslateTransform,而是使用Canvas.Left和Canvas.Top属性:

编辑:更新答案

以下是XAML:

<Canvas x:Name="canvas">
    <Thumb Name="myRoot"
            Canvas.Left="0" Canvas.Top="0"
            DragDelta="myRoot_DragDelta"
            MouseMove="myRoot_MouseMove"
            MouseDown="myRoot_MouseDown"
            MouseUp="myRoot_MouseUp">
        <Thumb.Template>
            <ControlTemplate>
                <Grid RenderTransformOrigin="0.5, 0.5">
                    <Rectangle Fill="AliceBlue"
                               Stroke="#FF0061CE"
                               StrokeThickness="1"
                               Width="100" Height="100"/>
                    <Grid.RenderTransform>
                        <RotateTransform x:Name="rotateTransform" />
                    </Grid.RenderTransform>
                </Grid>
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>
</Canvas>

我以为我是通过在用户控件上设置renderTransferMorigin=“0.5,0.5”来实现的?请检查:@Gilad我不确定这个链接对我有什么帮助,你能给我一个提示吗?尝试交换转换的顺序。它应该先平移,然后旋转。@Moozhe我这样做了,但是它会围绕画布的左上角点旋转,而不是图像的原点(我将RenderTransferMorigin设置为0.5,0.5)。我尝试了你的代码,虽然旋转部分看起来有点缓慢,但它还是工作了,至少在我的机器上,它没有我希望的那么顺利。这不是理想的方式。我会看看我是否能写一个更好的例子。我也看到了我在我的版本中看到的同样奇怪的行为。一旦旋转超过90度,当再次拖动时,它开始表现出奇怪的行为(复制:拖动到中间,旋转180度,而不是向任何方向拖动)。拇指在变换时不报告正确的增量值。拇指应该高于视觉树中的变换(其内容可以变换)。我会发布我的代码。
<Canvas x:Name="canvas">
    <Thumb Name="myRoot"
            Canvas.Left="0" Canvas.Top="0"
            DragDelta="myRoot_DragDelta"
            MouseMove="myRoot_MouseMove"
            MouseDown="myRoot_MouseDown"
            MouseUp="myRoot_MouseUp">
        <Thumb.Template>
            <ControlTemplate>
                <Grid RenderTransformOrigin="0.5, 0.5">
                    <Rectangle Fill="AliceBlue"
                               Stroke="#FF0061CE"
                               StrokeThickness="1"
                               Width="100" Height="100"/>
                    <Grid.RenderTransform>
                        <RotateTransform x:Name="rotateTransform" />
                    </Grid.RenderTransform>
                </Grid>
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>
</Canvas>
public partial class TestWindow : Window
{
    public TestWindow()
    {
        InitializeComponent();
    }

    Point? lastPosition = null;
    RotateTransform rotateTransform;

    private void myRoot_MouseDown(object sender, MouseButtonEventArgs e)
    {
        lastPosition = null;

        if (e.ChangedButton == MouseButton.Right)
            myRoot.CaptureMouse();
    }

    private void myRoot_MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Right)
            myRoot.ReleaseMouseCapture();
    }

    private void myRoot_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.RightButton == MouseButtonState.Pressed)
        {
            Point curPosition = Mouse.GetPosition(myRoot);

            if (lastPosition != null)
            {
                Point centerPoint = new Point(myRoot.ActualWidth / 2, myRoot.ActualWidth / 2);

                if (rotateTransform == null)
                    rotateTransform = (RotateTransform)myRoot.Template.FindName("rotateTransform", myRoot);

                rotateTransform.Angle = Math.Atan2(curPosition.Y - centerPoint.Y, curPosition.X - centerPoint.X) * 100;
            }

            lastPosition = curPosition;
            e.Handled = true;
        }
    }

    private void myRoot_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        Canvas.SetLeft(myRoot, Canvas.GetLeft(myRoot) + e.HorizontalChange);
        Canvas.SetTop(myRoot, Canvas.GetTop(myRoot) + e.VerticalChange);
    }
}