2012-06-04 2 views
0

사용자가 캔버스에 이미지를 끌어다 놓을 수 있도록 Thumb 클래스를 사용하고 있습니다. 오른쪽 버튼을 누르면, 나는 사용자가 이미지를 회전 할 수 있기를 바랍니다. 회전은 이미지의 중심을 기준으로합니다. 나는 내가 단지 드래그 앤 화면 주변의 이미지를 드롭 경우 작동 다음 XAML 코드 RotateTransform 및 TranslateTransform 결합

<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> 

그리고

bool isMouseDown = false; 
    Point pos; 
    double lastAngle = 0; 

    private void Canvas_MouseDown(object sender, MouseButtonEventArgs e) 
    { 
     isMouseDown = true; 
     lastAngle = rotateTransform.Angle; 
     pos = Mouse.GetPosition(canvas); 
    } 

    private void Canvas_MouseUp(object sender, MouseButtonEventArgs e) 
    { 
     isMouseDown = false; 
    } 

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

     var curPos = Mouse.GetPosition(canvas); 
     rotateTransform.Angle = lastAngle + (pos.Y - curPos.Y); 
    } 

    private void myRoot_DragDelta(object sender, DragDeltaEventArgs e) 
    { 
     translateTransform.X += e.HorizontalChange; 
     translateTransform.Y += e.VerticalChange; 
    } 

뒤에이 코드가 이미지 A를 회전 소량 (어떤 방향으로도 50도는 괜찮아 보인다.) 그러나 그 이상으로 이미지를 조작하면 화면이 예기치 않게 움직입니다.

변형을 다른 컨트롤로 이동하려고 시도 했으므로 변형을 허용하지 않고 수용할만한 결과를 얻지 못했습니다.

내 코드가 원하는대로 작동하도록하려면 어떻게해야합니까?

업데이트 : 이것은 내 미친 운전. 첫째, 오프셋으로 이동보다 그래픽을 회전 : 나는이 일을해야 내 마음에 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; 
    } 

를 사용하는 코드와 XAML을 변경했습니다. 그것은 내가 기대했던 것처럼 작동하지 않습니다. 이미지를 회전 시키지만 마우스를 계속 움직이면 바깥쪽으로 나선형으로 이상하게 움직입니다. 내가 무엇을 하든지, 어떤 순서로 내 변형을 실행하든간에 그것은 효과가 없습니다.

+0

확인이 아웃 : , http://stackoverflow.com/questions/2056338/center-of-rotation-after-translation/2063125#2063125 – Gilad

+0

@ 길라드이 링크가 어떻게 도움이되는지 잘 모르겠습니다. 힌트? – UrbanEsc

+0

변환 순서를 바꿔보십시오. 그것은 먼저 번역해야하며, 두 번째는 회전해야합니다. –

답변

0

Thumb을 래핑하기 위해 UserControl을 사용하는 이유가 확실하지 않습니다. 왜냐하면 여기에서 루트 요소로 작동 할 수 있어야하기 때문입니다. 편집

: 업데이트 대답 여기

은 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> 

그리고있어 여기에 TranslateTransform의 사용을 폐기하고 대신 위해 Canvas.LEFT 및 Canvas.Top 속성을 사용하여 involes 솔루션입니다 뒤에 코드 :

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); 
    } 
} 
+0

당신의 코드를 시험해 보았는데 회전 부분이 다소 느린 것처럼 보였습니다. 적어도 내 기계에서는 그다지 원활하지 못했습니다. – UrbanEsc

+0

이상적인 방법은 아닙니다. 내가 더 좋은 방법의 예를 쓸 수 있는지 알게 될 것이다. –

+0

나는 또한 나의 버전으로 보는 동일한 이상한 행동을 본다. 90도 이상 회전하면 다시 드래그 할 때 이상한 행동을 시작합니다. (복제 : 가운데로 드래그하고 180도 회전, 모든 방향으로 드래그) – UrbanEsc

0

좌표계의 중심이 아닌 객체의 중심을 기준으로 회전하려는 RotateTransform을 지정해야합니다 (기본값). 이렇게하려면 RotateTransform의 CenterX 및 CenterY 속성을 개체의 가운데로 설정합니다.

+0

나는 RenderTransformOrigin = "0.5,0.5"를 설정함으로써 그렇게했다고 생각했다. UserControl에? – UrbanEsc

+0

흠 - 네 말이 맞아 - 그리워. –