WPF画导航箭头,始终指向鼠标位置

发布时间 2023-07-27 14:09:49作者: HotSky

 

界面:

<Canvas x:Name="container">
    <Viewbox x:Name="player" Width="50" Height="50" RenderTransformOrigin="0.5,0.5">
        <Viewbox.RenderTransform>
            <TransformGroup>
                <RotateTransform Angle="0"/>
            </TransformGroup>
        </Viewbox.RenderTransform>
        <Path Fill="DodgerBlue" Data="M0,10 5,0 10,10 5,8" VerticalAlignment="Center" HorizontalAlignment="Center"></Path>
    </Viewbox>
</Canvas>

初始位置在窗口中央:

Point center;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    Point p = new Point((this.ActualWidth - player.ActualWidth) / 2, (this.ActualHeight - player.ActualHeight) / 2);
    center = new Point(p.X + player.ActualWidth / 2, p.Y + player.ActualHeight / 2);
    Canvas.SetLeft(player, p.X);
    Canvas.SetTop(player, p.Y);
}

获取鼠标坐标,并计算旋转角度:

protected override void OnPreviewMouseMove(MouseEventArgs e)
{
    base.OnPreviewMouseMove(e);
    Point p = e.GetPosition(container);
    Point p1 = new Point(p.X - center.X, p.Y - center.Y);
    SetAngle(p1);
}

void SetAngle(Point o)
{
    var tran = player.RenderTransform.GetTransform<RotateTransform>();
    var atan = System.Math.Atan(o.X / o.Y);
    if (o.X == 0d)
    {
        if (o.Y > 0)
            atan = System.Math.PI;
    }
    else if (o.Y == 0)
    {
        atan = o.X >= 0 ? System.Math.PI / 2 : -System.Math.PI / 2;
    }
    else if (o.X > 0)
    {
        if (o.Y < 0)
            atan = System.Math.Atan(o.X / -o.Y);
        else
            atan = System.Math.PI - System.Math.Atan(o.X / o.Y);
    }
    else
    {
        if (o.Y < 0)
            atan = System.Math.Atan(o.X / -o.Y);
        else
            atan = System.Math.PI + System.Math.Atan(-o.X / o.Y);
    }
    tran!.Angle = Math.RadianToAngle(atan);
}

帮助类:

public static class Math
{
    /// <summary>
    /// 弧度转角度
    /// </summary>
    /// <param name="radian"></param>
    /// <returns></returns>
    public static double RadianToAngle(double radian)
    {
        return 180 / System.Math.PI * radian;
    }

    public static double Length(Point p1, Point p2)
    {
        double x = p1.X - p2.X;
        double y = p1.Y - p2.Y;
        return System.Math.Sqrt(x * x + y * y);
    }
}
public static class WPFExtension
{
    public static T? GetTransform<T>(this Transform transform) where T : Transform
    {
        if (transform == null) return null;
        if(transform is TransformGroup group)
        {
            foreach (var item in group.Children)
            {
                if(item is T) return (T)item;
            }
        }
        return (T)transform;
    }
}