开发者

WPF: Apply a RenderTransform such that GetPosition is relative to center, not top-left

开发者 https://www.devze.com 2023-02-15 14:56 出处:网络
I am trying to drag the circle at A around so that it produces an angle relative to the hidden center element, B.

I am trying to drag the circle at A around so that it produces an angle relative to the hidden center element, B.

I'm using MouseEventArgs.GetPosition(IInputElement relativeTo), so:

Point p = args.GetPosition(B)

I'm getting points relative to the top-left of B, not its center, despite setting a RenderTransformOrigin of 0.5, 0.5 on B.

I know that I can comput开发者_JS百科e the correct offset manually: Easiest way to get the angle of mouse position in WPF relative to the center of a circle

WPF: Apply a RenderTransform such that GetPosition is relative to center, not top-left


The RenderTransformOrigin specifies the relative origin of any RenderTransform applied on B. Setting it does not in itself change the position of B, so it does not affect e.GetPosition(B) either.

e.GetPosition(B) in human language is "Give me the mouse position in the coordinate space of B. No matter how you change this coordinate space (by applying a render transform), relatively, the centre of B will aways be in its middle and it will depend on its size, so you will need to calculate its centre.

Also when you calculate the angle you need to make sure that you are using one and the same coordinate space. This code rotates A over the Centre, regardless of how they are positioned:

Point? dragStart;
    Point centrePoint;

    private void A_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var handle = sender as FrameworkElement;
        var parent = handle.Parent as FrameworkElement;

        dragStart = e.GetPosition(parent);

        var rotateCentre = Centre.TransformToVisual(A).Transform(new Point(Centre.ActualWidth / 2, Centre.ActualHeight / 2));
        A.RenderTransform = new RotateTransform { CenterX = rotateCentre.X, CenterY = rotateCentre.Y };

        centrePoint = Centre.TransformToVisual(handle.Parent as FrameworkElement).Transform(new Point(Centre.ActualWidth / 2, Centre.ActualHeight / 2));
        handle.CaptureMouse();
    }

    private void A_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragStart != null)
        {
            var current = e.GetPosition((sender as FrameworkElement).Parent as FrameworkElement);

            var angle = RadiansToDegrees(AngleAtoB(dragStart.Value, current, centrePoint));

            (A.RenderTransform as RotateTransform).Angle = angle;
        }
    }

    private void A_LostMouseCapture(object sender, MouseEventArgs e)
    {
        dragStart = null;
    }

    private void A_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        (sender as FrameworkElement).ReleaseMouseCapture();
    }

    internal static double AngleWithHorizontal(Point point, Point origin)
    {
        return Math.Atan2(point.Y - origin.Y, point.X - origin.X);
    }

    internal static double AngleAtoB(Point a, Point b, Point origin)
    {
        return AngleWithHorizontal(b, origin) - AngleWithHorizontal(a, origin);
    }

    private const double Const180OverPi = 180 / Math.PI;

    internal static double RadiansToDegrees(double angleInDegrees)
    {
        return angleInDegrees * Const180OverPi;
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消