更改自定义圆环图的起始角度和方向

Changing starting angle and direction of a custom doughnut chart

我正在尝试在 WPF 中创建圆环图并使用 this helpful previous answer

但是,目前 StartAngle 从 3 点钟位置开始,例如

如何更改此代码,使 StartAngle 从 12 点钟位置开始,角度按顺时针方向测量,例如

1] StartAngle = 0, EndAngle = 90 => 覆盖右上角。

2] StartAngle = 0, EndAngle = 180 => 覆盖右半边。

3] StartAngle = 0, EndAngle = 270 => 覆盖图表的四分之三。

我试过将 SweepDirection.Counterclockwise 更改为 SweepDirection.Clockwise,但这不起作用。我还尝试在我的 Arc class 中添加 ScaleTransformRotateTransform,如下所示。

WPF代码:

<Viewbox Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Grid Height="100" Width="200">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Rectangle x:Name="divider"  Fill="DimGray" Width="2" VerticalAlignment="Stretch" Height="70" Grid.Column="1" Grid.RowSpan="2"/>
        <notifications1:Arc
            Grid.Column="0"
            Stroke="DimGray"
            StrokeThickness="5"
            StartAngle="0" EndAngle="359.999"
            Margin="20"/>
        <notifications1:Arc
            Grid.Column="0"
            Stroke="{Binding DaySalesPercentage, Converter={StaticResource StorePerformanceToColourConverter}}"
            StrokeThickness="5"
            StartAngle="0" EndAngle="{Binding DaySalesPercentage, Converter={StaticResource StorePerformanceToAngleConverter}}"
            Margin="20"/>
        <Label Content="sales remaining today" 
               x:Name="testing"
               Foreground="{Binding IsDaySalesPercentageAvailable, Converter={StaticResource UnavailableStorePerformanceToColourConverter}}" 
               HorizontalContentAlignment="Center" 
               FontSize="9"
               FontWeight="DemiBold"
               VerticalAlignment="Top"
               Margin="0,0,0,0"
               Grid.Column="0"/>
        <Label Content="{Binding DaySalesPercentageLabel}" 
               x:Name="DaySalesPercentageLabel1"
                   Foreground="{Binding IsDaySalesPercentageAvailable, Converter={StaticResource UnavailableStorePerformanceToColourConverter}}"
                   HorizontalContentAlignment="Center"
                   FontSize="20"
                   FontWeight="DemiBold"
                   VerticalAlignment="Top"
                   Margin="0,28,0,0"
               Grid.Column="0"/>
        <Label Content="-£60" 
               x:Name="DaySalesPercentageLabel2"
               Foreground="{Binding IsDaySalesPercentageAvailable, Converter={StaticResource UnavailableStorePerformanceToColourConverter}}" 
               HorizontalContentAlignment="Center" 
               FontSize="10"
               FontWeight="DemiBold"
               VerticalAlignment="Top"
               Margin="0,50,0,0"
               Grid.Column="0"/>
    </Grid>
</Viewbox>

Arc.cs:

public class Arc : Shape
{
    public double StartAngle
    {
        get { return (double)GetValue(StartAngleProperty); }
        set { SetValue(StartAngleProperty, value); }
    }

    // Using a DependencyProperty as the backing store for StartAngle.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StartAngleProperty =
        DependencyProperty.Register("StartAngle", typeof(double), typeof(Arc), new PropertyMetadata(0.0, AnglesChanged));

    public double EndAngle
    {
        get { return (double)GetValue(EndAngleProperty); }
        set { SetValue(EndAngleProperty, value); }
    }

    // Using a DependencyProperty as the backing store for EndAngle.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EndAngleProperty =
        DependencyProperty.Register("EndAngle", typeof(double), typeof(Arc), new PropertyMetadata(0.0, AnglesChanged));


    protected override Geometry DefiningGeometry
    {
        get
        {
            return GetArcGeometry();
        }
    }

    private static void AnglesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var arc = d as Arc;
        if (arc != null)
            arc.InvalidateVisual();
    }

    private Geometry GetArcGeometry()
    {
        Point startPoint = PointAtAngle(Math.Min(StartAngle, EndAngle));
        Point endPoint = PointAtAngle(Math.Max(StartAngle, EndAngle));
        Size arcSize = new Size(Math.Max(0, (RenderSize.Width - StrokeThickness) / 2),
        Math.Max(0, (RenderSize.Height - StrokeThickness) / 2));
        bool isLargeArc = Math.Abs(EndAngle - StartAngle) > 180;
        StreamGeometry geom = new StreamGeometry();
        using (StreamGeometryContext context = geom.Open())
        {
            context.BeginFigure(startPoint, false, false);
            context.ArcTo(endPoint, arcSize, 0, isLargeArc,
            SweepDirection.Counterclockwise, true, false);
        }
        geom.Transform = new TranslateTransform(StrokeThickness / 2, StrokeThickness / 2);

        return geom;
    }

    private Point PointAtAngle(double angle)
    {
        double radAngle = angle * (Math.PI / 180);
        double xRadius = (RenderSize.Width - StrokeThickness) / 2;
        double yRadius = (RenderSize.Height - StrokeThickness) / 2;
        double x = xRadius + xRadius * Math.Cos(radAngle);
        double y = yRadius - yRadius * Math.Sin(radAngle);
        return new Point(x, y);
    }
}

我试过添加以下内容:

<notifications1:Arc
    Grid.Column="0"
    Stroke="{Binding DaySalesPercentage, Converter={StaticResource StorePerformanceToColourConverter}}"
    StrokeThickness="5"
    StartAngle="0" EndAngle="{Binding DaySalesPercentage, Converter={StaticResource StorePerformanceToAngleConverter}}"
    Margin="20">
    <notifications1:Arc.RenderTransform>
        <TransformGroup>
            <!-- Triple the size (scale) of the button in the Y direction. -->
            <ScaleTransform ScaleX="-1" ScaleY="1" />

            <!-- Rotate the button by 45 degrees. -->
            <RotateTransform Angle="90" />
        </TransformGroup>
    </notifications1:Arc.RenderTransform>
</notifications1:Arc>

像这样旋转和移动圆弧:

你差不多明白了

只需使用 LayoutTransform 而不是 RenderTransform

这里是 EndAngle = 120 和 LayoutTransform 的显示: