У меня на окне располагается 9 StackPanel, я делаю для них анимацию смены цвета при наведении мыши
У каждой панели разный цвет и соответственно менять тоже нужно разный цвет, а писать 9 раз этот код для каждой панели, ну понимаете...
Можно ли как то создать ресурс с параметрами (входным и выходным цветом)?
Ответ
Можно, но неочевидным образом.
К сожалению, в анимации невозможно использовать не Binding, не DynamicResource, поэтому придётся пойти обходным путём.
Идея такова: будем вместо цвета анимировать число от 0.0 до 1.0 и обратно, а цвет фона вычислим из начального и конечного цветов через конвертер.
Реализуем!
Итак, для начала конвертер, который будет интерполировать цвета. Он очень простой. Идея одолжена здесь
class ColorInterpolationConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object p, CultureInfo ci)
{
if (values.Contains(DependencyProperty.UnsetValue))
return Binding.DoNothing;
Color from = (Color)values[0];
Color to = (Color)values[1];
double ratio = (double)values[2];
return from + (to - from) * (float)ratio;
}
public object[] ConvertBack(object value, Type[] targetTypes, object p, CultureInfo ci)
{
throw new NotImplementedException();
}
}
Теперь, нам нужно задать начальный и конечный цвет. Это должны быть, по идее, attached property. Так же нам нужно attached property для текущего значения соотношения между начальным и конечным цветами, которое мы будем анимировать. Определяем их во вспомогательном классе:
static class ColorExtensions
{
#region attached property double Ratio
public static double GetRatio(DependencyObject obj) =>
(double)obj.GetValue(RatioProperty);
public static void SetRatio(DependencyObject obj, double value) =>
obj.SetValue(RatioProperty, value);
public static readonly DependencyProperty RatioProperty =
DependencyProperty.RegisterAttached(
"Ratio", typeof(double), typeof(ColorExtensions));
#endregion
#region attached property Color BaseColor
public static Color GetBaseColor(DependencyObject obj) =>
(Color)obj.GetValue(BaseColorProperty);
public static void SetBaseColor(DependencyObject obj, Color value) =>
obj.SetValue(BaseColorProperty, value);
public static readonly DependencyProperty BaseColorProperty =
DependencyProperty.RegisterAttached(
"BaseColor", typeof(Color), typeof(ColorExtensions));
#endregion
#region attached property Color HoverColor
public static Color GetHoverColor(DependencyObject obj) =>
(Color)obj.GetValue(HoverColorProperty);
public static void SetHoverColor(DependencyObject obj, Color value) =>
obj.SetValue(HoverColorProperty, value);
public static readonly DependencyProperty HoverColorProperty =
DependencyProperty.RegisterAttached(
"HoverColor", typeof(Color), typeof(ColorExtensions));
#endregion
}
Окей, теперь сам стиль.
Используем:
Результат:
Кода получилось довольно много, но в принципе, его можно повторно использовать. Если бы в анимации можно было бы задавать параметры более гибко, такая сложность бы не понадобилась.
Комментариев нет:
Отправить комментарий