WPF: примените RenderTransform так, чтобы GetPosition было относительно центра, а не верхнего левого угла. - PullRequest
1 голос
/ 08 марта 2011

Я пытаюсь перетащить круг в точке A так, чтобы он образовал угол относительно скрытого центрального элемента, B.

Я использую MouseEventArgs.GetPosition(IInputElement relativeTo), поэтому:

Point p = args.GetPosition(B)

Я получаю очки относительно левого верхнего угла B, а не его центра, несмотря на установку RenderTransformOrigin равным 0,5, 0,5 на B.

Я знаю, что могу вычислить правильное смещение вручную: Самый простой способ получить угол положения мыши в WPF относительно центра круга

enter image description here

1 Ответ

3 голосов
/ 10 марта 2011

RenderTransformOrigin указывает относительное происхождение любого RenderTransform, примененного к B. Установка его сама по себе не меняет положение B, поэтому она также не влияет на e.GetPosition(B).

e.GetPosition(B) на человеческом языке: «Дайте мне положение мыши в координатном пространстве B. Независимо от того, как вы измените это координатное пространство (применяя преобразование рендеринга), относительно, центр B всегда будет находиться в его среднее и оно будет зависеть от его размера, поэтому вам нужно будет рассчитать его центр.

Также, когда вы рассчитываете угол, вам необходимо убедиться, что вы используете одно и то же координатное пространство. Этот код вращается A над Centre независимо от того, как они расположены:

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;
    }
...