Изменение начального угла и направления пользовательской кольцевой диаграммы

Я пытаюсь создать кольцевую диаграмму в WPF и использую предыдущий полезный ответ.

Однако в настоящее время StartAngle начинается с положения 3 часов, например.

введите здесь описание изображения

Как я могу изменить этот код, чтобы StartAngle начинался с положения 12 часов, а угол измерялся по часовой стрелке, например.

1] StartAngle = 0, EndAngle = 90 => закрывает правый верхний угол.

2] StartAngle = 0, EndAngle = 180 => покрывает правую половину.

3] StartAngle = 0, EndAngle = 270 => покрывает три четверти графика.

Я пытался изменить SweepDirection.Counterclockwise на SweepDirection.Clockwise, но это не сработало. Я также попытался добавить ScaleTransform и RotateTransform в свой класс Arc, как показано ниже.

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>

Который вращает и перемещает дугу следующим образом:

введите здесь описание изображения


person Bhav    schedule 04.09.2019    source источник


Ответы (1)


ты почти понял

просто используйте LayoutTransform вместо RenderTransform

вот отображение EndAngle = 120 с LayoutTransform:

введите здесь описание изображения

person ASh    schedule 04.09.2019