Есть изображение
Требуется обвернуть картинку индикатором загрузки и менять цвет по мере продвижения индикатора
Ответ
Ну что же, давайте напишем стиль для ProgressBar'а, ведь в конце-концов вы показываете ProgressBar, правильно?
Для начала, нам нужен будет конвертер, превращающий угол в геометрию, описывающую наш круглый прогрессбар.
Вспомним тригонометрию и в путь!
class RoundProgressPathConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
CultureInfo culture)
{
if (values?.Contains(DependencyProperty.UnsetValue) != false)
return DependencyProperty.UnsetValue;
var v = (double)values[0]; // значение слайдера
var min = (double)values[1]; // минимальное значение
var max = (double)values[2]; // максимальное
var ratio = (v - min) / (max - min); // какую долю окружности закрашивать
var isFull = ratio >= 1; // для случая полной окружности нужна особая обработка
var angleRadians = 2 * Math.PI * ratio;
var angleDegrees = 360 * ratio;
// внешний радиус примем за 1, растянем в XAML'е.
var outerR = 1;
// как параметр передадим долю радиуса, которую занимает внутренняя часть
var innerR =
System.Convert.ToDouble(parameter, CultureInfo.InvariantCulture) * outerR;
// вспомогательные штуки: вектор направления вверх
var vector1 = new Vector(0, -1);
// ... и на конечную точку дуги
var vector2 = new Vector(Math.Sin(angleRadians), -Math.Cos(angleRadians));
var center = new Point();
var geo = new StreamGeometry();
geo.FillRule = FillRule.EvenOdd;
using (var ctx = geo.Open())
{
Size outerSize = new Size(outerR, outerR),
innerSize = new Size(innerR, innerR);
if (!isFull)
{
Point p1 = center + vector1 * outerR, p2 = center + vector2 * outerR,
p3 = center + vector2 * innerR, p4 = center + vector1 * innerR;
ctx.BeginFigure(p1, isFilled: true, isClosed: true);
ctx.ArcTo(p2, outerSize, angleDegrees, isLargeArc: angleDegrees > 180,
sweepDirection: SweepDirection.Clockwise, isStroked: true,
isSmoothJoin: false);
ctx.LineTo(p3, isStroked: true, isSmoothJoin: false);
ctx.ArcTo(p4, innerSize, -angleDegrees, isLargeArc: angleDegrees > 180,
sweepDirection: SweepDirection.Counterclockwise, isStroked: true,
isSmoothJoin: false);
Point diag1 = new Point(-outerR, -outerR),
diag2 = new Point(outerR, outerR);
ctx.BeginFigure(diag1, isFilled: false, isClosed: false);
ctx.LineTo(diag2, isStroked: false, isSmoothJoin: false);
}
else
{
Point p1 = center + vector1 * outerR, p2 = center - vector1 * outerR,
p3 = center + vector1 * innerR, p4 = center - vector1 * innerR;
ctx.BeginFigure(p1, isFilled: true, isClosed: true);
ctx.ArcTo(p2, outerSize, 180, isLargeArc: false,
sweepDirection: SweepDirection.Clockwise, isStroked: true,
isSmoothJoin: false);
ctx.ArcTo(p1, outerSize, 180, isLargeArc: false,
sweepDirection: SweepDirection.Clockwise, isStroked: true,
isSmoothJoin: false);
ctx.BeginFigure(p3, isFilled: true, isClosed: true);
ctx.ArcTo(p4, innerSize, 180, isLargeArc: false,
sweepDirection: SweepDirection.Clockwise, isStroked: true,
isSmoothJoin: false);
ctx.ArcTo(p3, innerSize, 180, isLargeArc: false,
sweepDirection: SweepDirection.Clockwise, isStroked: true,
isSmoothJoin: false);
}
}
geo.Freeze();
return geo;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
CultureInfo culture)
{
throw new NotSupportedException();
}
}
Окей, конвертер есть, теперь нам нужен сам стиль. Он несложен, единственный интересный пункт — состояние Indeterminate
Отлично, нам теперь нужно поменять цвета на кастомные, и можно запускать.
Обыкновенный:
То же, с IsIndeterminate="True"
(он вращается).
Комментариев нет:
Отправить комментарий