UWP Radial Progress Bar Image Fill

2019-07-11 07:14发布

问题:

I am using the Radial Progress Bar from the UWP ToolKit. I want to use this progress in a game that I creating. I have an image that I want to fill the foreground of the progress bar with. No matter what I try I cannot get the image to fill in the progress bar, in the manner a progress bar fills in.

I am currently trying to scale the image in the foreground but that isn't quite the effect I am going for.

XAML:

<toolKit:RadialProgressBar Width="316" Height="316" Minimum="0" Maximum="100" Value="{Binding Value}" Thickness="36"

                                   BorderBrush="Transparent" >
            <toolKit:RadialProgressBar.Foreground>
                <ImageBrush ImageSource="ms-appx:///Assets/progress2.png" >
                    <ImageBrush.Transform>
                        <ScaleTransform CenterX="0" CenterY="0" ScaleX="{Binding Scale}" ScaleY="{Binding Scale}" />
                    </ImageBrush.Transform>
                </ImageBrush>
            </toolKit:RadialProgressBar.Foreground>
        </toolKit:RadialProgressBar>

C#:

private int _value;
        public int Value
        {
            get => _value;
            set
            {
                if (_value != value)
                {
                    _value = value;
                    RaisePropertyChanged(nameof(Value));
                    Scale = 1.0-(100.0 - (316.0 * (Convert.ToDouble(value) / 100.0) / 316.0 * 100.0))/100.0;

                }
            }
        }

        private double _scale;
        public double Scale
        {
            get => _scale;
            set
            {
                if (_scale != value)
                {
                    _scale = value;
                    RaisePropertyChanged(nameof(Scale));
                }
            }
        }

Below is the effect that the above code creates:

Is there a way to fill a progress bar with an image?

回答1:

How about custom one using Win2d?

XAML:

<Grid Width="500" Height="500">
    <xaml:CanvasControl x:Name="CanvasControl" Draw="CanvasControl_OnDraw"/>

    <Slider Width="500" VerticalAlignment="Center" ValueChanged="RangeBase_OnValueChanged"/>
</Grid>

and behind it:

    private static Vector2 _centerPoint = new Vector2(250);
    private static float _radius = 200;
    private int _currentValue;
    private readonly List<Vector2> _points = new List<Vector2>();
    private readonly CanvasStrokeStyle _strokeStyle = new CanvasStrokeStyle
    {
        StartCap = CanvasCapStyle.Round,
        EndCap = CanvasCapStyle.Round
    };

    public MainPage()
    {
        InitializeComponent();
        GetPoints(100);
    }

    private void GetPoints(int i)
    {
        var radFactor = Math.PI / 180;
        var angleStep = 360f / i;

        for (int j = 0; j < i + 1; j++)
        {
            _points.Add(new Vector2(_centerPoint.X + _radius * (float)Math.Cos((angleStep * j + 90) * radFactor), 
                _centerPoint.Y + _radius * (float)Math.Sin((angleStep * j + 90) * radFactor)));
        }
    }

    private void CanvasControl_OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
    {
        for (int i = 0; i < _currentValue; i++)
        {
            args.DrawingSession.DrawLine(_points[i], _points[i + 1], Colors.LimeGreen, 24, _strokeStyle);
        }
    }

    private void RangeBase_OnValueChanged(object sender, RangeBaseValueChangedEventArgs e)
    {
        _currentValue = (int) e.NewValue;
        CanvasControl.Invalidate();
    }

and it should look like this:



回答2:

I have decided to go away from using a radial progress bar. I have learned about Image cliping. I am using the image clip along with a Rotation transformation to get the desired effect.

XAML:

 <Image Source="ms-appx:///Assets/Progress.png" Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" >
                <Image.Clip>
                    <RectangleGeometry Rect="{Binding Rect}" >
                        <RectangleGeometry.Transform>
                            <RotateTransform CenterX="{Binding CenterXY}" CenterY="{Binding CenterXY}" Angle="{Binding Angle}" />
                        </RectangleGeometry.Transform>
                    </RectangleGeometry>
                </Image.Clip>
            </Image>

C#:

private int _value;
        public int Value
        {
            get => _value;
            set
            {
                if (_value != value)
                {
                    _value = value;
                    RaisePropertyChanged(nameof(Value));
                    Angle = 144 - 1.44 * value;
                }
            }
        }