diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs index c8e78d0..b03c187 100644 --- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs +++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs @@ -229,7 +229,7 @@ namespace Wpf_AiSportsMicrospace.Common if (k.Name != "right_ankle" && k.Name != "left_ankle") continue; - double x = k.X; + double x = 1920 - k.X; double y = k.Y; if (Math.Abs(x - cx) <= halfW && diff --git a/Wpf_AiSportsMicrospace/Common/Utils.cs b/Wpf_AiSportsMicrospace/Common/Utils.cs index 014089b..ea5781e 100644 --- a/Wpf_AiSportsMicrospace/Common/Utils.cs +++ b/Wpf_AiSportsMicrospace/Common/Utils.cs @@ -367,7 +367,7 @@ namespace Wpf_AiSportsMicrospace.Common { cfg.Point1, cfg.Point2, cfg.Point3, cfg.Point4, cfg.Point5, cfg.Point6, - cfg.Point7, cfg.Point8, cfg.Point9, cfg.Point10 + cfg.Point7, cfg.Point8, cfg.Point9 }; // 取前 pointCount 个点 diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml index 7cfde0b..84e0cea 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml @@ -1,57 +1,154 @@ - + mc:Ignorable="d" + d:DesignHeight="900" + d:DesignWidth="1920"> + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs index 4d2df00..21d03ca 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs +++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs @@ -1,21 +1,10 @@ -using System; -using System.Collections.Generic; +using System; using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; using System.Windows.Threading; namespace Wpf_AiSportsMicrospace.MyUserControl @@ -25,9 +14,16 @@ namespace Wpf_AiSportsMicrospace.MyUserControl /// public partial class CoverFlowControl : UserControl {// 新增事件:进度条完成 - public event Action ProgressCompleted; + public event Action? ProgressCompleted; public ObservableCollection Images { get; set; } = new ObservableCollection(); private int _selectedIndex = 0; + private bool _isAnimating; + private int _pendingSlideSteps; + + private const double CardWidth = 346; + private const double CardHeight = 534; + private const double CardGap = 30; // 卡片之间水平间距 + private const double SlideDurationMs = 420; // 动画时长 public int SelectedIndex { @@ -40,10 +36,8 @@ namespace Wpf_AiSportsMicrospace.MyUserControl else if (value >= Images.Count) _selectedIndex = 0; else _selectedIndex = value; - for (int i = 0; i < Images.Count; i++) - Images[i].IsSelected = i == _selectedIndex; - - UpdateLayoutWithAnimation(); + UpdateSelectionFlags(); + RefreshCards(instant: true); // 启动进度条动画 //var current = Images[_selectedIndex]; @@ -56,7 +50,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl { InitializeComponent(); DataContext = this; - Loaded += (s, e) => UpdateLayoutWithAnimation(true); + Loaded += CoverFlowControl_Loaded; //var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(5) }; //timer.Tick += (s, e) => @@ -68,9 +62,21 @@ namespace Wpf_AiSportsMicrospace.MyUserControl //}; //timer.Start(); } - private EventHandler _renderHandler; + private EventHandler? _renderHandler; - private CoverFlowItem _currentItem; + private CoverFlowItem? _currentItem; + + private void CoverFlowControl_Loaded(object sender, RoutedEventArgs e) + { + if (Images.Count > 0) + { + UpdateSelectionFlags(); + RefreshCards(instant: true); + } + + CarouselCanvas.Focus(); + Keyboard.Focus(CarouselCanvas); + } /// /// 针对当前选中项启动进度条动画 @@ -104,25 +110,11 @@ namespace Wpf_AiSportsMicrospace.MyUserControl _currentItem = item; item.Progress = 0; - var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter; - if (container == null) return; - - var canvas = FindVisualChild(container); - var spark = FindVisualChild(canvas); - if (spark != null) - spark.Visibility = Visibility.Visible; - _renderHandler = (s, e) => { if (_currentItem.Progress < 1) { _currentItem.Progress += 0.01; // 控制速度 - if (spark != null) - { - var pos = GetSparkPosition(_currentItem.Progress, 150, 200); - Canvas.SetLeft(spark, pos.X - spark.Width / 2); - Canvas.SetTop(spark, pos.Y - spark.Height / 2); - } } else { @@ -147,139 +139,320 @@ namespace Wpf_AiSportsMicrospace.MyUserControl if (_currentItem != null) { _currentItem.Progress = 0; - //_currentItem.IsSelected = true; - - var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(_currentItem) as ContentPresenter; - if (container != null) - { - var canvas = FindVisualChild(container); - var spark = FindVisualChild(canvas); - if (spark != null) - spark.Visibility = Visibility.Collapsed; - } - _currentItem = null; } } - - private Point GetSparkPosition(double progress, double width, double height) + private void UpdateSelectionFlags() { - double perimeter = 2 * (width + height); - double len = progress * perimeter; - - if (len <= width) return new Point(len, 0); // 上边 - len -= width; - if (len <= height) return new Point(width, len); // 右边 - len -= height; - if (len <= width) return new Point(width - len, height); // 下边 - len -= width; - return new Point(0, height - len); // 左边 + for (int i = 0; i < Images.Count; i++) + Images[i].IsSelected = i == _selectedIndex; } - private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + private int WrapIndex(int index) { - if (sender is Border border) + if (Images.Count == 0) return 0; + var m = index % Images.Count; + if (m < 0) m += Images.Count; + return m; + } + + private double SlotDistance => CardWidth + CardGap; + + private double XFarLeft => 0; + private double XLeft => SlotDistance; + private double XCenter => SlotDistance * 2; + private double XRight => SlotDistance * 3; + private double XFarRight => SlotDistance * 4; + private double XOffLeft => -SlotDistance; + private double XOffRight => SlotDistance * 5; + + private void SetCard(ContentPresenter card, CoverFlowItem? item, double left, double opacity = 1) + { + card.Content = item; + Canvas.SetLeft(card, left); + Canvas.SetTop(card, 0); + card.Opacity = opacity; + } + + private void RefreshCards(bool instant) + { + if (Images.Count == 0) return; + + var farLeft = Images[WrapIndex(_selectedIndex - 2)]; + var left = Images[WrapIndex(_selectedIndex - 1)]; + var center = Images[WrapIndex(_selectedIndex)]; + var right = Images[WrapIndex(_selectedIndex + 1)]; + var farRight = Images[WrapIndex(_selectedIndex + 2)]; + + SetCard(CardFarLeft, farLeft, XFarLeft, 1); + SetCard(CardLeft, left, XLeft, 1); + SetCard(CardCenter, center, XCenter, 1); + SetCard(CardRight, right, XRight, 1); + SetCard(CardFarRight, farRight, XFarRight, 1); + + // spare stays hidden offscreen + SetCard(CardSpare, null, XOffRight, 0); + + if (!instant) + return; + } + + private void Carousel_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + { + if (e.Delta < 0) SlideLeft(); + else if (e.Delta > 0) SlideRight(); + e.Handled = true; + } + + private void Carousel_PreviewKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Right || e.Key == Key.Down) { - var container = ItemsHost.ItemContainerGenerator.ContainerFromItem(border.DataContext) as ContentPresenter; - if (container != null) - { - int index = ItemsHost.ItemContainerGenerator.IndexFromContainer(container); - SelectedIndex = index; - } + SlideLeft(); + e.Handled = true; + } + else if (e.Key == Key.Left || e.Key == Key.Up) + { + SlideRight(); + e.Handled = true; } } - private void UpdateLayoutWithAnimation(bool instant = false) + private void CardLeft_Click(object sender, MouseButtonEventArgs e) { - double centerX = ActualWidth / 2; - double spacing = 530; - double sideScale = 0.98; - double centerScale = 1.33; + RequestSlide(-1); + } - for (int i = 0; i < ItemsHost.Items.Count; i++) + private void CardRight_Click(object sender, MouseButtonEventArgs e) + { + RequestSlide(+1); + } + + private void CardFarLeft_Click(object sender, MouseButtonEventArgs e) + { + RequestSlide(-2); + } + + private void CardFarRight_Click(object sender, MouseButtonEventArgs e) + { + RequestSlide(+2); + } + + private void CardCenter_Click(object sender, MouseButtonEventArgs e) + { + // center click: treat as selecting current (already selected) + } + + private void RequestSlide(int steps) + { + if (Images.Count == 0) return; + if (steps == 0) return; + + _pendingSlideSteps += steps; + TryRunNextSlide(); + } + + private void TryRunNextSlide() + { + if (_isAnimating) return; + if (_pendingSlideSteps == 0) return; + + if (_pendingSlideSteps > 0) { - var container = ItemsHost.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter; - if (container == null) continue; - - var border = FindVisualChild(container); - if (border == null) continue; - - var transformGroup = border.RenderTransform as TransformGroup; - var scale = transformGroup.Children[0] as ScaleTransform; - var translate = transformGroup.Children[1] as TranslateTransform; - - double targetX; - double targetScale; - double targetOpacity; - - if (i == SelectedIndex) - { - targetX = centerX - 175; - targetScale = centerScale; - targetOpacity = 1.0; - } - else if (i == SelectedIndex - 1 || (SelectedIndex == 0 && i == Images.Count - 1)) - { - targetX = centerX - spacing -175; - targetScale = sideScale; - targetOpacity = 1.0; - } - else if (i == SelectedIndex + 1 || (SelectedIndex == Images.Count - 1 && i == 0)) - { - targetX = centerX + spacing - 175; - targetScale = sideScale; - targetOpacity = 1.0; - } - else - { - targetX = centerX - 175; - targetScale = sideScale; - targetOpacity = 0.0; - } - - if (instant) - { - translate.X = targetX; - scale.ScaleX = scale.ScaleY = targetScale; - border.Opacity = targetOpacity; - } - else - { - translate.BeginAnimation(TranslateTransform.XProperty, - new DoubleAnimation(targetX, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); - scale.BeginAnimation(ScaleTransform.ScaleXProperty, - new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); - scale.BeginAnimation(ScaleTransform.ScaleYProperty, - new DoubleAnimation(targetScale, TimeSpan.FromMilliseconds(400)) { EasingFunction = new QuadraticEase() }); - border.BeginAnimation(Border.OpacityProperty, - new DoubleAnimation(targetOpacity, TimeSpan.FromMilliseconds(400))); - } + _pendingSlideSteps--; + AnimateLeftOne(); + } + else + { + _pendingSlideSteps++; + AnimateRightOne(); } } - private static T FindVisualChild(DependencyObject obj) where T : DependencyObject + private void AnimateLeftOne() { - if (obj == null) return null; - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) + if (_isAnimating) return; + if (Images.Count == 0) return; + + _isAnimating = true; + StopProgress(); + + var newSelected = WrapIndex(_selectedIndex + 1); + var incomingFarRight = Images[WrapIndex(newSelected + 2)]; + + // Prepare spare entering from the right (to far-right slot) + SetCard(CardSpare, incomingFarRight, XOffRight, 1); + + var sb = new Storyboard { FillBehavior = FillBehavior.Stop }; + var ease = new CubicEase { EasingMode = EasingMode.EaseOut }; + var dur = TimeSpan.FromMilliseconds(SlideDurationMs); + + void AddMove(FrameworkElement fe, double toX) { - var child = VisualTreeHelper.GetChild(obj, i); - if (child is T target) return target; - var result = FindVisualChild(child); - if (result != null) return result; + var anim = new DoubleAnimation + { + To = toX, + Duration = new Duration(dur), + EasingFunction = ease + }; + Storyboard.SetTarget(anim, fe); + Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Left)")); + sb.Children.Add(anim); } - return null; + + void AddFade(FrameworkElement fe, double toOpacity) + { + var anim = new DoubleAnimation + { + To = toOpacity, + Duration = new Duration(dur), + EasingFunction = ease + }; + Storyboard.SetTarget(anim, fe); + Storyboard.SetTargetProperty(anim, new PropertyPath("Opacity")); + sb.Children.Add(anim); + } + + // Far-left card slides out to left and fades + AddMove(CardFarLeft, XOffLeft); + AddFade(CardFarLeft, 0); + + // Shift others left by one slot, spare enters to far-right + AddMove(CardLeft, XFarLeft); + AddMove(CardCenter, XLeft); + AddMove(CardRight, XCenter); + AddMove(CardFarRight, XRight); + AddMove(CardSpare, XFarRight); + + sb.Completed += (_, _) => + { + _selectedIndex = newSelected; + UpdateSelectionFlags(); + + // After shift left: + // new FarLeft = old Left + // new Left = old Center + // new Center = old Right + // new Right = old FarRight + // new FarRight = old Spare + var oldFarLeftContent = (CoverFlowItem?)CardFarLeft.Content; + var oldLeftContent = (CoverFlowItem?)CardLeft.Content; + var oldCenterContent = (CoverFlowItem?)CardCenter.Content; + var oldRightContent = (CoverFlowItem?)CardRight.Content; + var oldFarRightContent = (CoverFlowItem?)CardFarRight.Content; + var oldSpareContent = (CoverFlowItem?)CardSpare.Content; + + SetCard(CardFarLeft, oldLeftContent, XFarLeft, 1); + SetCard(CardLeft, oldCenterContent, XLeft, 1); + SetCard(CardCenter, oldRightContent, XCenter, 1); + SetCard(CardRight, oldFarRightContent, XRight, 1); + SetCard(CardFarRight, oldSpareContent, XFarRight, 1); + + SetCard(CardSpare, null, XOffRight, 0); + + _isAnimating = false; + TryRunNextSlide(); + }; + + sb.Begin(this, true); + } + + private void AnimateRightOne() + { + if (_isAnimating) return; + if (Images.Count == 0) return; + + _isAnimating = true; + StopProgress(); + + var newSelected = WrapIndex(_selectedIndex - 1); + var incomingFarLeft = Images[WrapIndex(newSelected - 2)]; + + // Prepare spare entering from the left (to far-left slot) + SetCard(CardSpare, incomingFarLeft, XOffLeft, 1); + + var sb = new Storyboard { FillBehavior = FillBehavior.Stop }; + var ease = new CubicEase { EasingMode = EasingMode.EaseOut }; + var dur = TimeSpan.FromMilliseconds(SlideDurationMs); + + void AddMove(FrameworkElement fe, double toX) + { + var anim = new DoubleAnimation + { + To = toX, + Duration = new Duration(dur), + EasingFunction = ease + }; + Storyboard.SetTarget(anim, fe); + Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Left)")); + sb.Children.Add(anim); + } + + void AddFade(FrameworkElement fe, double toOpacity) + { + var anim = new DoubleAnimation + { + To = toOpacity, + Duration = new Duration(dur), + EasingFunction = ease + }; + Storyboard.SetTarget(anim, fe); + Storyboard.SetTargetProperty(anim, new PropertyPath("Opacity")); + sb.Children.Add(anim); + } + + // Far-right card slides out to right and fades + AddMove(CardFarRight, XOffRight); + AddFade(CardFarRight, 0); + + // Shift others right by one slot, spare enters to far-left + AddMove(CardRight, XFarRight); + AddMove(CardCenter, XRight); + AddMove(CardLeft, XCenter); + AddMove(CardFarLeft, XLeft); + AddMove(CardSpare, XFarLeft); + + sb.Completed += (_, _) => + { + _selectedIndex = newSelected; + UpdateSelectionFlags(); + + var oldFarLeftContent = (CoverFlowItem?)CardFarLeft.Content; + var oldLeftContent = (CoverFlowItem?)CardLeft.Content; + var oldCenterContent = (CoverFlowItem?)CardCenter.Content; + var oldRightContent = (CoverFlowItem?)CardRight.Content; + var oldFarRightContent = (CoverFlowItem?)CardFarRight.Content; + var oldSpareContent = (CoverFlowItem?)CardSpare.Content; + + // After shift right: + // new FarRight = old Right + // new Right = old Center + // new Center = old Left + // new Left = old FarLeft + // new FarLeft = old Spare + SetCard(CardFarRight, oldRightContent, XFarRight, 1); + SetCard(CardRight, oldCenterContent, XRight, 1); + SetCard(CardCenter, oldLeftContent, XCenter, 1); + SetCard(CardLeft, oldFarLeftContent, XLeft, 1); + SetCard(CardFarLeft, oldSpareContent, XFarLeft, 1); + + SetCard(CardSpare, null, XOffRight, 0); + + _isAnimating = false; + TryRunNextSlide(); + }; + + sb.Begin(this, true); } public void SlideLeft() { - StopProgress(); - SelectedIndex++; + RequestSlide(+1); } public void SlideRight() { - StopProgress(); - SelectedIndex--; + RequestSlide(-1); } } } \ No newline at end of file diff --git a/Wpf_AiSportsMicrospace/MyUserControl/SportUserItem.xaml b/Wpf_AiSportsMicrospace/MyUserControl/SportUserItem.xaml index fa3610b..c189e3f 100644 --- a/Wpf_AiSportsMicrospace/MyUserControl/SportUserItem.xaml +++ b/Wpf_AiSportsMicrospace/MyUserControl/SportUserItem.xaml @@ -13,23 +13,25 @@ - + + + - - - diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/jump_rope.gif b/Wpf_AiSportsMicrospace/Resources/Img/new/group/jump_rope.gif new file mode 100644 index 0000000..2607a19 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/jump_rope.gif differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/out.png b/Wpf_AiSportsMicrospace/Resources/Img/new/group/out.png new file mode 100644 index 0000000..ac675e5 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/out.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/pre_user.png b/Wpf_AiSportsMicrospace/Resources/Img/new/group/pre_user.png new file mode 100644 index 0000000..b23cc0f Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/pre_user.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_bg.png b/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_bg.png new file mode 100644 index 0000000..9c732f7 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_bg.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_title.png b/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_title.png new file mode 100644 index 0000000..18df745 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/test_title.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/group/top_bg.png b/Wpf_AiSportsMicrospace/Resources/Img/new/group/top_bg.png new file mode 100644 index 0000000..d5e1d2d Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/group/top_bg.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_1.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_1.png new file mode 100644 index 0000000..ce75226 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_1.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_2.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_2.png new file mode 100644 index 0000000..b627297 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_2.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_3.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_3.png new file mode 100644 index 0000000..43c96ad Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_3.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_4.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_4.png new file mode 100644 index 0000000..dbba7fa Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_4.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_5.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_5.png new file mode 100644 index 0000000..00f3d83 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/card_5.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_bg.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_bg.png new file mode 100644 index 0000000..d6bdd41 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_bg.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_title.png b/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_title.png new file mode 100644 index 0000000..52edc57 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/home/home_title.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom - 复制.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom - 复制.png new file mode 100644 index 0000000..ecae47e Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom - 复制.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom.png new file mode 100644 index 0000000..ecae47e Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/bottom.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/head_top.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/head_top.png new file mode 100644 index 0000000..bd197df Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/head_top.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/jump_bg.jpg b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jump_bg.jpg new file mode 100644 index 0000000..40abe3a Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jump_bg.jpg differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping.gif b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping.gif new file mode 100644 index 0000000..8dd0cdd Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping.gif differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping1.gif b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping1.gif new file mode 100644 index 0000000..f2351ad Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/jumping1.gif differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat.png new file mode 100644 index 0000000..fc81881 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat1.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat1.png new file mode 100644 index 0000000..0b03559 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/mat1.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/people.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/people.png new file mode 100644 index 0000000..f9496c4 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/people.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/right_hand.gif b/Wpf_AiSportsMicrospace/Resources/Img/new/long/right_hand.gif new file mode 100644 index 0000000..da6317d Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/right_hand.gif differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img - 复制.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img - 复制.png new file mode 100644 index 0000000..2b1b145 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img - 复制.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img.png new file mode 100644 index 0000000..2b1b145 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/rotate_img.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/tip.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/tip.png new file mode 100644 index 0000000..924e428 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/tip.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/title.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/title.png new file mode 100644 index 0000000..75564a8 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/title.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/top.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/top.png new file mode 100644 index 0000000..f326234 Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/top.png differ diff --git a/Wpf_AiSportsMicrospace/Resources/Img/new/long/win_bg.png b/Wpf_AiSportsMicrospace/Resources/Img/new/long/win_bg.png new file mode 100644 index 0000000..6cdfbbe Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/new/long/win_bg.png differ diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml b/Wpf_AiSportsMicrospace/Views/Home.xaml index 7678e57..fa2ead2 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml @@ -5,13 +5,13 @@ xmlns:gif="http://wpfanimatedgif.codeplex.com" xmlns:hc="https://handyorg.github.io/handycontrol" Height="1080" Width="1920" Loaded="Window_Loaded" Unloaded="Home_Unloaded"> - + - + @@ -66,14 +66,7 @@ - + diff --git a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs index a2bb600..90ebd69 100644 --- a/Wpf_AiSportsMicrospace/Views/Home.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/Home.xaml.cs @@ -1,4 +1,4 @@ -using AiSportsMicrospaceDB.DBContext; +using AiSportsMicrospaceDB.DBContext; using AiSportsMicrospaceDB.Entities; using Common; using Microsoft.EntityFrameworkCore; @@ -48,13 +48,13 @@ namespace Wpf_AiSportsMicrospace // --------------------- CoverFlow 加载 --------------------- coverFlow.Images.Add(new CoverFlowItem { - ImageUri = GetResourceUri("test_img/test_rope.png"), + ImageUri = GetResourceUri("new/home/card_1.png"), ProgressColor1 = "#215bc7", ProgressColor2 = "#fc640e", }); coverFlow.Images.Add(new CoverFlowItem { - ImageUri = GetResourceUri("play_img/play_music.png"), + ImageUri = GetResourceUri("new/home/card_2.png"), ProgressColor1 = "#e73d42", ProgressColor2 = "#fd8212" @@ -62,11 +62,25 @@ namespace Wpf_AiSportsMicrospace coverFlow.Images.Add(new CoverFlowItem { //ImageUri = GetResourceUri("Album/home_history.png"), - ImageUri = GetResourceUri("play_img/whack_mole.png"), + ImageUri = GetResourceUri("new/home/card_3.png"), ProgressColor1 = "#e73d42", ProgressColor2 = "#215bc7" }); + // 为了演示 5 个入口,这里复用前面 3 张图补足到 5 张 + coverFlow.Images.Add(new CoverFlowItem + { + ImageUri = GetResourceUri("new/home/card_4.png"), + ProgressColor1 = "#215bc7", + ProgressColor2 = "#fc640e", + }); + coverFlow.Images.Add(new CoverFlowItem + { + ImageUri = GetResourceUri("new/home/card_5.png"), + ProgressColor1 = "#e73d42", + ProgressColor2 = "#fd8212" + }); + // 默认选中第3张 coverFlow.SelectedIndex = 0; Loaded += Window_Loaded; diff --git a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml index b98e9c0..3e5945c 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml +++ b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml @@ -9,27 +9,27 @@ Height="1080" Width="1920" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded"> - + - - - + + + HorizontalAlignment="Left" VerticalAlignment="Top" Margin="488,95,0,0" Width="1072" Height="750"/> @@ -45,7 +45,7 @@ /> - + @@ -68,14 +68,14 @@ - - + + - - + + - + diff --git a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs index 91731d2..33cfc77 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpLong/StandingLeap.xaml.cs @@ -54,7 +54,7 @@ namespace Views.JumpLong private JumpLongPoints _Points; private int _sportType = 0; // 0:未开始 1:运动中 2:运动结束展示排行榜 - + private bool isBack = false; //是否返回主页 #endregion public StandingLeap() @@ -101,23 +101,24 @@ namespace Views.JumpLong try { if (humans == null || humans.Count == 0) return; + //左手返回 + int leftWaving = DetectLeftHandRaise(humans); + if (leftWaving == 5) + { + //_mainWin.WebcamClient.StopExtract(); + // 举左手逻辑,例如结束动画或退出 + if (isBack) return; // 已经返回过主页了,避免重复执行 + _mainWin.HumanFrameUpdated -= this.OnFrameUpdated; + isBack = true; + var newPage = new Home(); + _mainWin?.SwitchPageWithMaskAnimation(newPage, true); + + return; // 提前退出 + } //举手检测 未开始 :退出& 开始 运动中:不检测 2.结束:继续测试 & 退出 if (_sportType != 1) { - //左手返回 - int leftWaving = DetectLeftHandRaise(humans); - if (leftWaving == 5) - { - //_mainWin.HumanFrameUpdated -= this.OnFrameUpdated; - //_mainWin.WebcamClient.StopExtract(); - - // 举左手逻辑,例如结束动画或退出 - var newPage = new Home(); - _mainWin?.SwitchPageWithMaskAnimation(newPage, true); - return; // 提前退出 - } - //右手判断 int rightWaving = DetectRightHandRaise(humans); if (rightWaving >= 3 && _sportType == 0) //举手完成 开始跳远检测 @@ -213,7 +214,7 @@ namespace Views.JumpLong // }; // TipBox.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation); - // }); + // });; //}); } @@ -238,9 +239,9 @@ namespace Views.JumpLong ImageBehavior.GetAnimationController(centerImg4).Play(); await Task.Delay(2100); _sport.Stop();//关闭运动 - _mainWin.FacialRecognitionEvent -= this.HumanPredicting; + //_mainWin.FacialRecognitionEvent -= this.HumanPredicting; count.Text = counts; - time.Text = _sport.GetFormatTimes(); + //time.Text = _sport.GetFormatTimes(); ShowRope(); if (!_sport.IsCounting) { @@ -283,7 +284,7 @@ namespace Views.JumpLong if (i == 8) { centerImg4.Visibility = Visibility.Hidden; - centerImg3.Visibility = Visibility.Visible; + //centerImg3.Visibility = Visibility.Visible; } if (i == 1) { @@ -521,7 +522,7 @@ namespace Views.JumpLong Utils.PlayBackgroundMusic("countdown_3.mp3", false); _mainWin.ShowCountDownAnimation(); - centerImg3.Visibility = Visibility.Hidden; + //centerImg3.Visibility = Visibility.Hidden; centerImg4.Visibility = Visibility.Visible; //if (_sport?.IsCounting == true) //_mainWin.WebcamClient.OnExtractFrame += this.OnFrameExtracted; @@ -583,7 +584,7 @@ namespace Views.JumpLong videoImage.Opacity = 1; centerImg1.Opacity = 0; centerImg2.Opacity = 0; - centerImg3.Opacity = 0; + //centerImg3.Opacity = 0; }); } } diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml index 05cabf9..7be6134 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml @@ -8,14 +8,14 @@ mc:Ignorable="d" Height="1080" Width="1920" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded"> - + @@ -76,7 +76,7 @@ Margin="0,168" /> - + diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs index 5868a77..cd90fcc 100644 --- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs +++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs @@ -2,6 +2,7 @@ using Common; using Dto; using Emgu.CV.Flann; +using Emgu.CV.Structure; using Enum; using HandyControl.Controls; using Microsoft.EntityFrameworkCore; @@ -66,7 +67,7 @@ namespace Wpf_AiSportsMicrospace.Views private readonly object _updateLock = new object(); private readonly Dictionary _jumpStatus = new Dictionary(); private GroupJumpRopeContext _groupJumpRopeContext; - + Image tipImage; public GroupJumpRope() { InitializeComponent(); @@ -138,13 +139,14 @@ namespace Wpf_AiSportsMicrospace.Views } private void ShowCenterTip(string imagePath, TimeSpan duration) { - var tipImage = new Image + tipImage = new Image { Source = new BitmapImage(new Uri(imagePath, UriKind.Absolute)), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Opacity = 0, Margin = new Thickness(0, -100, 0, 0), + Name= "TipImage" }; // 增加图片的大小,调整比例 @@ -164,26 +166,26 @@ namespace Wpf_AiSportsMicrospace.Views tipImage.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation); // 定时移除,并且渐变消失 - Task.Delay(duration).ContinueWith(_ => - { - Dispatcher.Invoke(() => - { - // 渐变消失动画 - var fadeOutAnimation = new DoubleAnimation - { - From = 1, - To = 0, - Duration = TimeSpan.FromSeconds(1.5) - }; - tipImage.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation); + //Task.Delay(duration).ContinueWith(_ => + //{ + // Dispatcher.Invoke(() => + // { + // // 渐变消失动画 + // var fadeOutAnimation = new DoubleAnimation + // { + // From = 1, + // To = 0, + // Duration = TimeSpan.FromSeconds(1.5) + // }; + // tipImage.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation); - // 完成后移除图片 - fadeOutAnimation.Completed += (s, e) => - { - userBox.Children.Remove(tipImage); - }; - }); - }); + // // 完成后移除图片 + // fadeOutAnimation.Completed += (s, e) => + // { + // userBox.Children.Remove(tipImage); + // }; + // }); + //}); } private void MediaPlayer_MediaEnded(object sender, EventArgs e) @@ -210,6 +212,7 @@ namespace Wpf_AiSportsMicrospace.Views if (leftWaving == 5) { // 举左手逻辑,例如结束动画或退出 + _isCountdownStarted = true; var newPage = new Home(); _mainWin?.SwitchPageWithMaskAnimation(newPage, true); return; // 提前退出 @@ -238,7 +241,9 @@ namespace Wpf_AiSportsMicrospace.Views private async void StartCountdown(int start = 3) { + tipImage.Visibility = Visibility.Collapsed; _mainWin.ShowCountDownAnimation(); + //_currentCountdown = start; Utils.PlayBackgroundMusic("countdown_3.mp3", false); diff --git a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj index d4734d2..0ba84d4 100644 --- a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj +++ b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj @@ -48,6 +48,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -139,6 +162,75 @@ Always + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + Always