Итак, я пытаюсь создать границу с анимированными градиентными цветами и заархивировать эффект RGB. Почему-то цвет просто статичен (как на картинке ниже), он вообще не анимируется, и здесь мне нужна помощь. Документация ограничена и буквально ничего не объясняет по этому поводу, например, в документации WPF: Статический цветовой градиент
Простой код, который я использовал:
private LinearGradientBrush gradientBrush;
private Border brd;
public MainPage()
{
InitializeComponent();
gradientBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 0),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = Colors.Red, Offset = 0.0f },
new GradientStop { Color = Colors.Green, Offset = 0.5f },
new GradientStop { Color = Colors.Blue, Offset = 1.0f }
}
};
brd = new Border
{
StrokeThickness = 5,
BackgroundColor = Colors.White,
Stroke = gradientBrush,
Padding = 10,
Content = new Label
{
Text = "Hello",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Colors.Black,
}
};
Content = new Grid
{
Children = { brd }
};
}
private async void AnimateGradient()
{
while (true)
{
await Task.WhenAll(
AnimateColor(gradientBrush.GradientStops[0], Colors.Red, Colors.Purple, 2000),
AnimateColor(gradientBrush.GradientStops[1], Colors.Green, Colors.Yellow, 2000),
AnimateColor(gradientBrush.GradientStops[2], Colors.Blue, Colors.Cyan, 2000)
);
await Task.WhenAll(
AnimateColor(gradientBrush.GradientStops[0], Colors.Purple, Colors.Red, 2000),
AnimateColor(gradientBrush.GradientStops[1], Colors.Yellow, Colors.Green, 2000),
AnimateColor(gradientBrush.GradientStops[2], Colors.Cyan, Colors.Blue, 2000)
);
}
}
private Task AnimateColor(GradientStop gradientStop, Color fromColor, Color toColor, uint duration)
{
var animation = new Animation(v =>
{
gradientStop.Color = new Color(
(float)(fromColor.Red + v * (toColor.Red - fromColor.Red)),
(float)(fromColor.Green + v * (toColor.Green - fromColor.Green)),
(float)(fromColor.Blue + v * (toColor.Blue - fromColor.Blue)),
(float)(fromColor.Alpha + v * (toColor.Alpha - fromColor.Alpha))
);
InvalidateMeasure();
OnPropertyChanged(nameof(brd));
});
animation.Commit(this, gradientStop.GetHashCode().ToString(), length: duration, easing: Easing.Linear);
OnPropertyChanged(nameof(gradientBrush));
return Task.Delay((int)duration);
}
protected override async void OnAppearing()
{
base.OnAppearing();
AnimateGradient();
}
Отлаженный и протестированный код выполняется.
.Net 8, Мауи 8.0.70, Windows
Для создания простых анимаций я иногда создаю фиктивный ContentView и устанавливаю
Для достижения желаемого эффекта, думаю, достаточно обновить StartPoint
, EndPoint
ваших LinearGradientBrush
:
private LinearGradientBrush gradientBrush;
private Border brd;
private ContentView animation = new ContentView();
public MainPage()
{
InitializeComponent();
gradientBrush = new LinearGradientBrush
{
StartPoint = new Point(0, 0),
EndPoint = new Point(1, 1),
GradientStops = new GradientStopCollection
{
new GradientStop { Color = Colors.Red, Offset = 0.0f },
new GradientStop { Color = Colors.Green, Offset = 0.5f },
new GradientStop { Color = Colors.Blue, Offset = 1.0f }
}
};
brd = new Border
{
StrokeThickness = 250,
BackgroundColor = Colors.White,
Stroke = gradientBrush,
Padding = 10,
Content = new Label
{
Text = "Hello",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Colors.Black,
}
};
Content = new Grid
{
Children = { brd }
};
animation.TranslationX = 0;
animation.TranslationY = 0;
animation.TranslateTo(2 * Math.PI * 10, 0, 2000 * 10);
animation.PropertyChanged += (s, e) =>
{
double x = Math.Cos(animation.TranslationX);
double y = Math.Sin(animation.TranslationX);
gradientBrush.StartPoint = new Point(-x * 0.5 + 0.5, -y * 0.5 + 0.5);
gradientBrush.EndPoint = new Point(x * 0.5 + 0.5, y * 0.5 + 0.5);
};
}
Хм... да, это было бы хорошим обходным путем. Не могли бы вы также объяснить, почему цвета не работают?
Я могу воспроизвести вопрос на основе вашего кода. Вы можете поднять проблему на GitHub. Но если вы примените цвет анимированного градиента к Border.Background
вместо Border.Stroke
, это сработает.
Итак, в качестве обходного пути вы можете вложить меньшую границу (или другой контейнер) во внешнюю границу. Установите для фона внутренней границы белый цвет, а для фона внешней границы — анимированную градиентную кисть.
brd = new Border
{
Background = gradientBrush,
Padding = 10,
Content = new Border
{
Margin = 5,
StrokeThickness = 0,
BackgroundColor= Colors.White,
Content = new Label
{
Text = "Hello",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Colors.Black,
}
}
};
Какую версию и платформу .NET вы используете?