diff --git a/Wpf_AiSportsMicrospace/Common/Utils.cs b/Wpf_AiSportsMicrospace/Common/Utils.cs index a3f8b10..e7d30c7 100644 --- a/Wpf_AiSportsMicrospace/Common/Utils.cs +++ b/Wpf_AiSportsMicrospace/Common/Utils.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows.Controls; using System.Windows.Media; +using System.Windows.Media.Imaging; +using WpfAnimatedGif; namespace Wpf_AiSportsMicrospace.Common { @@ -91,5 +95,118 @@ namespace Wpf_AiSportsMicrospace.Common }); return total; } + + + //public static Uri countDownGif = new Uri("/Resources/Img/Album/1.gif", UriKind.Relative); + + //倒计时动画 + public static Grid GetCountdownAnimation(Grid needAnimationGrid) + { + //string projectRoot = Path.Combine(AppContext.BaseDirectory, @"..\..\.."); + //string gifPath = Path.Combine(projectRoot, "Resources", "Img", "gif" , "time_3.gif"); + //var uri = new Uri(gifPath, UriKind.Absolute); + //var uri = new Uri("/Resources/Img/gif/time_3.gif", UriKind.Relative); + BitmapImage uri = GetGif("/time_3.gif"); + var grid = new Grid + { + Height = 1080, + Width = 1920, + Name = "countdownGridAnimation", + }; + + var border = new Border + { + Height = 1080, + Width = 1920, + Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)), // 半透明黑色背景 + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center + }; + grid.Children.Add(border); + var image = new System.Windows.Controls.Image + { + Source = uri, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Width = 1920, + Height = 1080, + }; + ImageBehavior.SetAnimatedSource(image, uri); + ImageBehavior.SetAutoStart(image , true); + grid.Children.Add(image); + needAnimationGrid.Children.Add(grid); + + + Debug.WriteLine($"GIF尺寸: {uri.PixelWidth}x{uri.PixelHeight}"); + Debug.WriteLine($"GIF URI: {uri.UriSource}"); + // 动画播放完成后移除Grid + Task.Run(async () => + { + await Task.Delay(3300); // 等待4秒钟,确保动画播放完毕 + Application.Current.Dispatcher.Invoke(() => + { + needAnimationGrid.Children.Remove(grid); + }); + }); + return grid; + } + + + //预加载资源 + private static readonly Dictionary _cache = new Dictionary(); + private static bool _isPreloaded = false; + + // 预加载所有需要的 GIF + public static void PreloadGifs() + { + if (_isPreloaded) return; + var gifPaths = new[] + { + "/time_3.gif", + // 添加其他需要预加载的 GIF 路径 + }; + + foreach (var path in gifPaths) + { + LoadGifToCache(path); + } + + _isPreloaded = true; + } + + private static void LoadGifToCache(string relativePath) + { + try + { + string projectRoot = Path.Combine(AppContext.BaseDirectory, @"..\..\.."); + string topPath = Path.Combine(projectRoot, "Resources", "Img", "gif"); + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.UriSource = new Uri(topPath + relativePath, UriKind.Relative); + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; // 立即加载到内存 + bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache; // 忽略磁盘缓存 + bitmapImage.EndInit(); + bitmapImage.Freeze(); // 冻结对象,使其线程安全 + + + _cache[relativePath] = bitmapImage; + } + catch (Exception ex) + { + Debug.WriteLine($"预加载GIF失败 {relativePath}: {ex.Message}"); + } + } + + public static BitmapImage GetGif(string relativePath) + { + if (_cache.TryGetValue(relativePath, out var cachedImage)) + { + return cachedImage; + } + + // 如果缓存中没有,立即加载 + LoadGifToCache(relativePath); + return _cache.GetValueOrDefault(relativePath); + } } } diff --git a/Wpf_AiSportsMicrospace/Resources/Img/gif/time_3.gif b/Wpf_AiSportsMicrospace/Resources/Img/gif/time_3.gif new file mode 100644 index 0000000..464122f Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/gif/time_3.gif differ diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml b/Wpf_AiSportsMicrospace/Views/Home.xaml index 76580db..6d3bc55 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml @@ -16,6 +16,7 @@ VerticalAlignment="Top" Width="615" Margin="0,50,0,0" + MouseDown="Image_MouseDown" /> diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs index 4ce9c30..6d42220 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs @@ -36,6 +36,8 @@ namespace Wpf_AiSportsMicrospace public partial class Home : UserControl { public static Uri loadingImage = new Uri("/Resources/Img/Album/1.gif", UriKind.Relative); + public static Uri countDownGif = new Uri("/Resources/Img/gif/time_3.gif", UriKind.Relative); + private Main _mainWin => Application.Current.MainWindow as Main; public Home() @@ -61,6 +63,7 @@ namespace Wpf_AiSportsMicrospace { _mainWin.HumanFrameUpdated += OnHumanFrameUpdated; _mainWin.WebcamClient.StartExtract(); + Utils.PreloadGifs(); } private void Home_Unloaded(object sender, RoutedEventArgs e) { @@ -163,5 +166,11 @@ namespace Wpf_AiSportsMicrospace mainWin?.SwitchPageWithMaskAnimation(newPage, true); } } + + private void Image_MouseDown(object sender, MouseButtonEventArgs e) + { + var mainWin = Application.Current.MainWindow as Main; + mainWin!.ShowCountDownAnimation(); + } } } diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml index 90a1517..39ecd6a 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl" + xmlns:gif="http://wpfanimatedgif.codeplex.com" mc:Ignorable="d" Height="1080" Width="1920" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded"> @@ -138,5 +139,5 @@ - + diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index 128e024..8a549d0 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -220,12 +220,13 @@ namespace Wpf_AiSportsMicrospace.Views private DateTime _lastUpdateTime = DateTime.Now; private void StartCountdown(int start = 3) { - _currentCountdown = start; + _mainWin.ShowCountDownAnimation(); + //_currentCountdown = start; - countdownText.Text = _currentCountdown.ToString(); - countdownGrid.Visibility = Visibility.Visible; + //countdownText.Text = _currentCountdown.ToString(); + //countdownGrid.Visibility = Visibility.Visible; - _lastUpdateTime = DateTime.Now; + //_lastUpdateTime = DateTime.Now; Utils.PlayBackgroundMusic("countdown_3.mp3", false); } @@ -630,24 +631,43 @@ namespace Wpf_AiSportsMicrospace.Views grid.Children.Add(scoreText); ScoreGrid.Children.Add(grid); } + showElement("RankingGrid"); + //var rankingGrid = FindName("RankingGrid") as Grid; + //if (rankingGrid == null) return; - var rankingGrid = FindName("RankingGrid") as Grid; - if (rankingGrid == null) return; - - rankingGrid.Visibility = Visibility.Visible; - var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(600)); - rankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeIn); + //rankingGrid.Visibility = Visibility.Visible; + //var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(600)); + //rankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeIn); } - // 控制排行榜隐藏(渐隐动画) - public void HideRankingBoard() + /* + * 控制元素隐藏(渐隐动画 + * time: 动画持续时间(毫秒) + * name: 元素名称 + */ + public void HideElement(string name , int time) { - var rankingGrid = FindName("RankingGrid") as Grid; - if (rankingGrid == null) return; + var Element = FindName(name) as Grid; + if (Element == null) return; - var fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(600)); - fadeOut.Completed += (s, e) => rankingGrid.Visibility = Visibility.Collapsed; - rankingGrid.BeginAnimation(UIElement.OpacityProperty, fadeOut); + var fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(time)); + fadeOut.Completed += (s, e) => Element.Visibility = Visibility.Collapsed; + Element.BeginAnimation(UIElement.OpacityProperty, fadeOut); + } + + /* + * 控制元素限时(渐隐动画 + * time: 动画持续时间(毫秒) + * name: 元素名称 + */ + public void showElement(string name, int time = 600 ) + { + var Element = FindName(name) as FrameworkElement; + if (Element == null) return; + + Element.Visibility = Visibility.Visible; + var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(time)); + Element.BeginAnimation(UIElement.OpacityProperty, fadeIn); } } diff --git a/Wpf_AiSportsMicrospace/Views/Main.xaml b/Wpf_AiSportsMicrospace/Views/Main.xaml index 64bcb66..43d4407 100644 --- a/Wpf_AiSportsMicrospace/Views/Main.xaml +++ b/Wpf_AiSportsMicrospace/Views/Main.xaml @@ -4,9 +4,24 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.Views" + xmlns:gif="http://wpfanimatedgif.codeplex.com" mc:Ignorable="d" WindowState="Maximized"> + + + + + - + \ No newline at end of file diff --git a/Wpf_AiSportsMicrospace/Views/Main.xaml.cs b/Wpf_AiSportsMicrospace/Views/Main.xaml.cs index 6897fc1..c55d42c 100644 --- a/Wpf_AiSportsMicrospace/Views/Main.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Main.xaml.cs @@ -14,6 +14,7 @@ using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Media.Media3D; using Wpf_AiSportsMicrospace.Common; +using WpfAnimatedGif; using Yztob.AiSports.Inferences.Abstractions; using Yztob.AiSports.Inferences.Things; using Yztob.AiSports.Sensors.Abstractions; @@ -64,6 +65,8 @@ namespace Wpf_AiSportsMicrospace.Views //StartHeartbeatMonitor(); // 默认显示首页 MainContent.Content = new Home(); + + ImageBehavior.AddAnimationCompletedHandler(time3, TimeDown); } private void StartFrameProcessing() { @@ -347,5 +350,36 @@ namespace Wpf_AiSportsMicrospace.Views maskTop.RenderTransform.BeginAnimation(TranslateTransform.YProperty, topInAnim); maskBottom.RenderTransform.BeginAnimation(TranslateTransform.YProperty, bottomInAnim); } + + public void ShowElement(string name, int time = 600) + { + var Element = FindName(name) as FrameworkElement; + if (Element == null) return; + + Element.Visibility = Visibility.Visible; + var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(time)); + Element.BeginAnimation(UIElement.OpacityProperty, fadeIn); + } + + int num = 1; + public void ShowCountDownAnimation() + { + ImageBehavior.SetRepeatBehavior(time3, new RepeatBehavior(2)); + ImageBehavior.SetRepeatBehavior(time3, new RepeatBehavior(1)); + CountTimeGrid.Visibility = Visibility.Visible; + time3.Visibility = Visibility.Visible; + ImageBehavior.GetAnimationController(time3).Play(); + } + + private void TimeDown(object? sender, RoutedEventArgs? e) + { + //MessageBox.Show("播放完啦");// 弹提示框 + ImageBehavior.GetAnimationController(time3).Pause(); + CountTimeGrid.Visibility = Visibility.Hidden; + time3.Visibility = Visibility.Hidden; + num++; + } } + + } \ No newline at end of file diff --git a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj index 31ee9ef..50a781f 100644 --- a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj +++ b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj @@ -40,6 +40,7 @@ + @@ -208,6 +209,9 @@ Always + + Always + Always