首页 > 解决方案 > 何时设置 islargearch UWP

问题描述

我必须设置 IsLArgeArc 但我不能准确地做到这一点。

用户控件.xaml:

<UserControl
x:Class="Pointer_Answer_UWP.RadialSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Pointer_Answer_UWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="207"
d:DesignWidth="207">

<Grid>
    <Grid x:Name="GridBase" Width="207" Height="207" Background="#FFD7B6B6">
        <Ellipse Fill="#FFC7C7C7"/>
        <Grid Height="207" Width="207" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Path Stroke="#FF34A1ED" StrokeThickness="7" x:Name="arcPath" StrokeEndLineCap="Round" StrokeStartLineCap="Round" RenderTransformOrigin="0.5,0.5">
                <Path.RenderTransform>
                    <CompositeTransform TranslateX="3.5" TranslateY="3.5"/>
                </Path.RenderTransform>
                <Path.Data>
                    <PathGeometry>
                        <PathFigure x:Name="myArcStart" StartPoint="7.612,61.6317">
                            <ArcSegment x:Name="myArc" IsLargeArc="False" Point="78.3221,197.6221" Size="100,100"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>
        </Grid>
        <Canvas x:Name="CanvasVolume" Width="207" Height="207" RenderTransformOrigin="0.5,0.5">
            <Canvas.RenderTransform>
                <CompositeTransform x:Name="CompositePoint" Rotation="0"/>
            </Canvas.RenderTransform>
            <Ellipse x:Name="VolumePoint" Width="20" Height="20" Fill="#9923678A" PointerPressed="VolumePoint_PointerPressed" Canvas.Top="{x:Bind TopPosition, Mode=OneWay}" Canvas.Left="{x:Bind LeftPosition, Mode=OneWay}"/>
        </Canvas>
    </Grid>
</Grid>

用户控件.xaml.cs:

public sealed partial class RadialSlider : UserControl, INotifyPropertyChanged
{
    private double topPosition = 55.2317;
    public double TopPosition
    {
        get => topPosition;
        set
        {
            topPosition = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TopPosition)));
        }
    }

    private double leftPosition = 1.112;
    public double LeftPosition
    {
        get => leftPosition;
        set
        {
            leftPosition = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LeftPosition)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public RadialSlider()
    {
        this.InitializeComponent();
    }



    private void VolumePoint_PointerPressed(object sender, PointerRoutedEventArgs e)
    {
        RadialSlider radialSlider = this as RadialSlider;
        Point puntopressd = e.GetCurrentPoint(CanvasVolume).Position;

        PointerEventHandler moved = null;
        moved = (s, args) =>
        {
            CanvasVolume.CapturePointer(e.Pointer);
            Point puntomoved = e.GetCurrentPoint(CanvasVolume).Position;

            double puntoX = puntomoved.X;
            double puntoY = puntomoved.Y;
            double raggio = 100;

            double halfWidth = CanvasVolume.ActualHeight / 2;
            double slashLength = Math.Sqrt((Math.Abs(puntoY - halfWidth) * Math.Abs(puntoY - halfWidth) + (Math.Abs(halfWidth - puntoX) * Math.Abs(halfWidth - puntoX))));

            double coordinataX = CanvasVolume.ActualHeight / 2 + ((puntoX - halfWidth) * raggio / slashLength) - VolumePoint.Width / 2;
            double coordinataY = puntoY - ((puntoY - halfWidth) * (slashLength - raggio) / slashLength) - VolumePoint.Width / 2;

            double angolo = GetAngle(new Point((CanvasVolume.ActualHeight / 2 + ((puntoX - halfWidth) * raggio / slashLength)) - 3.5, (puntoY - ((puntoY - halfWidth) * (slashLength - raggio) / slashLength)) - 3.5), new Size(CanvasVolume.Width, CanvasVolume.Width));

            LeftPosition = coordinataX;
            TopPosition = coordinataY;

            //myArc.IsLargeArc = angolo < 113 ? true : false;

            myArc.Point = new Point((CanvasVolume.ActualHeight / 2 + ((puntoX - halfWidth) * raggio / slashLength)) -3.5, (puntoY - ((puntoY - halfWidth) * (slashLength - raggio) / slashLength)) - 3.5);
        };

        PointerEventHandler released = null;
        released = (s, args) =>
        {
            Point puntoreleas = e.GetCurrentPoint(CanvasVolume).Position;

            CanvasVolume.PointerMoved -= moved;
            CanvasVolume.PointerReleased -= released;
        };
        CanvasVolume.PointerMoved += moved;
        CanvasVolume.PointerReleased += released;
    }

    public enum Quadrants : int { nw = 2, ne = 1, sw = 4, se = 3 }
    private double GetAngle(Point point, Size size)
    {
        var X = point.X - (size.Width / 2d);
        var Y = size.Height - point.Y - (size.Height / 2d);
        var Hypot = Math.Sqrt(X * X + Y * Y);
        var Value = Math.Asin(Y / Hypot) * 180 / Math.PI;
        var Quadrant = (X >= 0) ? (Y >= 0) ? Quadrants.ne : Quadrants.se : (Y >= 0) ? Quadrants.nw : Quadrants.sw;
        switch (Quadrant)
        {
            case Quadrants.ne: Value = 090 - Value; break;
            case Quadrants.nw: Value = 270 + Value; break;
            case Quadrants.se: Value = 090 - Value; break;
            case Quadrants.sw: Value = 270 + Value; break;
        }
        return Value;
    }
}

如何准确计算何时设​​置 IsLargeArc 以获得正确结果?我尝试在 ArcSegment 达到 180° 时计算它的角度,但我无法得到正确的结果。

使用 GetAngle 我得到了角度,但我无法正确使用数据。我该如何进行?

感谢帮助。

标签: c#uwp

解决方案


考虑到 360 度的角度环绕,尝试使用 Math.Sin 函数,如下所示。顺便说一句,在这种情况下,要交给 GetAngle 的尺寸应该是 Size(raggio * 2, raggio * 2)。

double angolo = GetAngle(new Point(
      (CanvasVolume.ActualHeight / 2 + ((puntoX - halfWidth) * raggio / slashLength)) - 3.5,
      (puntoY - ((puntoY - halfWidth) * (slashLength - raggio) / slashLength)) - 3.5 
    ), new Size(raggio * 2, raggio * 2)
);

// BTW, it's also possible to calculate the angle at once with the handy Math.Atan2.
// double angolo = 180.0 - Math.Atan2(puntoX - halfWidth, puntoY - halfWidth) * 180.0 / Math.PI;

myArc.IsLargeArc = Math.Sin((angolo - 113) * Math.PI / 180.0) < 0.0;// ? true : false;

推荐阅读