With the help of this question and answer, I have managed to create a radial progress bar. This implements the arc drawing concept where the arc binds to the start and end angles.
The problem I have now is that I would like the progress bar to have radial gradient from the center of the arc. This gives the progress bar a "linear gradient" from the inside of the arc to the outside of the arc. I am trying to apply the radial gradient on the stroke of the arc (the Foreground property of the ProgressBar), but this applies the radial gradient at the center of the arc stroke, not the center of the arc object (as seen below).
When the arc is at 100% (or anything above 75%), the center of the stroke is at the center of the arc, which produces the desired result.
How can I consistently adjust the center of the radial gradient to the center of the arc so that the desired gradient is applied at all fill percentages? Or is there a better solution/approach to this problem?
Since the RadialGradient
you are using is most likely Relative
, it will change its center depending on the actual size of the arc.
When the arc is at 75% or higher, the Geometry
generated by Arc
is at its maximum Width
and Height
and therefore stable and covering the entire control.
What you want to do is, draw the entire circle and mask out the parts that are outside of the "original" arc. Easies way to do that in your case is to replace the Arc.OnRender
method with this:
Arc.cs
protected override void OnRender(DrawingContext drawingContext)
{
// half the width and height of the Arc
double radiusX = RenderSize.Width / 2;
double radiusY = RenderSize.Height / 2;
// the outlines of the "original" Arc geometry
PathGeometry clip = GetArcGeometry().GetWidenedPathGeometry(
new Pen(Stroke, StrokeThickness));
// draw only in the area of the original arc
drawingContext.PushClip(clip);
drawingContext.DrawEllipse(Stroke, null, new Point(radiusX, radiusY), radiusX, radiusY);
drawingContext.Pop();
}
Explanation
- Get the unmodified
Geometry
as calculated by the original code (GetArcGeometry
)
- Extend it with the
Pen
that was previously used to draw the arc (GetWidenedPathGeometry
)
- Instruct the
DrawingContext
to ignore anything outside of that area (Push(clip)
)
- Draw a full circle with the gradient (
DrawEllipse
)
- Instruct the
DrawingContext
to ignore the clip
from now on (Pop
)
Result
A not so great, but easy to implement solution. You need to tweak the xaml so that instead of having an arc with the radial gradient increase in angle as the progress increases, have an arc with the required gradient behind an arc with gray colour. The gray arc reduces in angle to unveil the background arc with the correct radial gradient.