using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace FasdDesktopUi.Basics.UserControls { public partial class Badge : UserControl { private readonly Storyboard _sparkleStoryboard; private const double SparkleBaseScale = 0.6; public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(Badge), new PropertyMetadata("Beta")); public bool IsSparkleEnabled { get { return (bool)GetValue(IsSparkleEnabledProperty); } set { SetValue(IsSparkleEnabledProperty, value); } } public static readonly DependencyProperty IsSparkleEnabledProperty = DependencyProperty.Register(nameof(IsSparkleEnabled), typeof(bool), typeof(Badge), new PropertyMetadata(false, OnIsSparkleEnabledChanged)); public Badge() { InitializeComponent(); _sparkleStoryboard = CreateSparkleStoryboard(); UpdateSparkleState(); } private static void OnIsSparkleEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as Badge; control?.UpdateSparkleState(); } private void BadgeControl_Loaded(object sender, RoutedEventArgs e) { UpdateSparkleState(); } private void BadgeControl_Unloaded(object sender, RoutedEventArgs e) { StopSparkles(); } private void UpdateSparkleState() { if (SparkleCanvas == null || _sparkleStoryboard == null) { return; } if (IsSparkleEnabled) { SparkleCanvas.Visibility = Visibility.Visible; _sparkleStoryboard.Begin(this, true); return; } SparkleCanvas.Visibility = Visibility.Collapsed; StopSparkles(); } private void StopSparkles() { _sparkleStoryboard?.Stop(this); if (SparkleTopRight != null) { SparkleTopRight.Opacity = 0; if (SparkleTopRight.RenderTransform is ScaleTransform topTransform) { topTransform.ScaleX = SparkleBaseScale; topTransform.ScaleY = SparkleBaseScale; } } if (SparkleBottomLeft != null) { SparkleBottomLeft.Opacity = 0; if (SparkleBottomLeft.RenderTransform is ScaleTransform bottomTransform) { bottomTransform.ScaleX = SparkleBaseScale; bottomTransform.ScaleY = SparkleBaseScale; } } } private Storyboard CreateSparkleStoryboard() { var storyboard = new Storyboard { RepeatBehavior = RepeatBehavior.Forever }; AddKeyFrames(storyboard, SparkleTopRight, "Opacity", (0.00, 0.0), (0.18, 1.0), (0.42, 0.0), (2.20, 0.0)); AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)", (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale)); AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)", (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale)); AddKeyFrames(storyboard, SparkleBottomLeft, "Opacity", (0.00, 0.0), (1.00, 0.0), (1.18, 1.0), (1.42, 0.0), (2.20, 0.0)); AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)", (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale)); AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)", (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale)); return storyboard; } private static void AddKeyFrames(Storyboard storyboard, DependencyObject target, string targetProperty, params (double TimeSeconds, double Value)[] frames) { var animation = new DoubleAnimationUsingKeyFrames(); foreach (var frame in frames) { animation.KeyFrames.Add(new LinearDoubleKeyFrame(frame.Value, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(frame.TimeSeconds)))); } Storyboard.SetTarget(animation, target); Storyboard.SetTargetProperty(animation, new PropertyPath(targetProperty)); storyboard.Children.Add(animation); } } }