diff --git a/Wpf_AiSportsMicrospace/App.xaml b/Wpf_AiSportsMicrospace/App.xaml
index 7854626..61792fe 100644
--- a/Wpf_AiSportsMicrospace/App.xaml
+++ b/Wpf_AiSportsMicrospace/App.xaml
@@ -2,6 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.Views"
+ xmlns:conv="clr-namespace:Wpf_AiSportsMicrospace.Converter"
+
StartupUri="Views/Main.xaml">
@@ -10,6 +12,8 @@
+
+
diff --git a/Wpf_AiSportsMicrospace/Common/SportOperate.cs b/Wpf_AiSportsMicrospace/Common/SportOperate.cs
index 83f0d72..7148e16 100644
--- a/Wpf_AiSportsMicrospace/Common/SportOperate.cs
+++ b/Wpf_AiSportsMicrospace/Common/SportOperate.cs
@@ -155,7 +155,7 @@ namespace Wpf_AiSportsMicrospace.Common
}
var duration = DateTime.Now - _raiseStartTime.Value;
- if (duration.TotalSeconds >= 3)
+ if (duration.TotalSeconds >= 1)
{
_raiseStartTime = null;
_wristStartTime = null;
diff --git a/Wpf_AiSportsMicrospace/Converter/DotColorConverter.cs b/Wpf_AiSportsMicrospace/Converter/DotColorConverter.cs
new file mode 100644
index 0000000..509040c
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/Converter/DotColorConverter.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Media;
+using Wpf_AiSportsMicrospace.MyUserControl;
+
+namespace Wpf_AiSportsMicrospace.Converter
+{
+ public class DotColorConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is bool b && b)
+ return Brushes.Red;
+ return Brushes.Green;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ => throw new NotImplementedException();
+ }
+}
diff --git a/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs b/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs
index 3f01bd6..6190c8b 100644
--- a/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs
+++ b/Wpf_AiSportsMicrospace/Dto/MusicJumpRopeContext.cs
@@ -50,6 +50,8 @@ namespace Dto
}
};
+ public Dictionary> MusicBeatsDic;
+
public MusicJumpRopeContext()
{
CirclePositions = new List<(double XNorm, double YNorm)>
@@ -58,6 +60,8 @@ namespace Dto
(0.50, 0.88),
};
+ MusicBeatsDic = MusicBeats["1"].GroupBy(b => (int)Math.Ceiling(b) - 1).ToDictionary(g => g.Key, g => g.ToList());
+
UserList = new List();
UserNumberList = new List();
Sports = new List();
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml b/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml
new file mode 100644
index 0000000..08a15d6
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml.cs
new file mode 100644
index 0000000..6111311
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/BeatScrollDots.xaml.cs
@@ -0,0 +1,136 @@
+using Emgu.CV.Flann;
+using HandyControl.Controls;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Text;
+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;
+
+namespace Wpf_AiSportsMicrospace.MyUserControl
+{
+ public partial class BeatScrollDots : UserControl
+ {
+ public ObservableCollection Dots { get; set; } = new ObservableCollection();
+
+ public BeatScrollDots()
+ {
+ InitializeComponent();
+ DataContext = this;
+ }
+
+ public int DotCount
+ {
+ get => (int)GetValue(DotCountProperty);
+ set => SetValue(DotCountProperty, value);
+ }
+
+ public static readonly DependencyProperty DotCountProperty =
+ DependencyProperty.Register(nameof(DotCount), typeof(int), typeof(BeatScrollDots),
+ new PropertyMetadata(0, OnDotCountChanged));
+
+ private static void OnDotCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is BeatScrollDots ctrl)
+ ctrl.GenerateDots();
+ }
+
+ private void GenerateDots()
+ {
+ Dots.Clear();
+ for (int i = 0; i < DotCount; i++)
+ Dots.Add(new DotItem { IsSelected = false });
+ }
+
+ public void SetSelected(int index, bool selected)
+ {
+ if (index >= 0 && index < Dots.Count)
+ Dots[index].IsSelected = selected;
+ }
+
+ public Thickness DotSpacing
+ {
+ get => (Thickness)GetValue(DotSpacingProperty);
+ set => SetValue(DotSpacingProperty, value);
+ }
+
+ public static readonly DependencyProperty DotSpacingProperty =
+ DependencyProperty.Register(nameof(DotSpacing), typeof(Thickness), typeof(BeatScrollDots), new PropertyMetadata(new Thickness(5, 0, 5, 0)));
+
+ public void ScrollToDotCenter(int index, bool mirror = false)
+ {
+ if (scrollViewer == null || Dots.Count == 0) return;
+
+ double step = 20 + DotSpacing.Left + DotSpacing.Right;
+ double totalWidth = Dots.Count * step;
+ double dotCenter = index * step + step / 2;
+
+ double targetOffset = !mirror
+ ? dotCenter - scrollViewer.ActualWidth / 2
+ : totalWidth - dotCenter - scrollViewer.ActualWidth / 2;
+
+ targetOffset = System.Math.Max(0, System.Math.Min(targetOffset, scrollViewer.ScrollableWidth));
+ scrollViewer.ScrollToHorizontalOffset(targetOffset);
+ }
+
+ public void UpdateSpacingForCount(int count)
+ {
+ if (count <= 0) count = 1;
+ double spacing = (ActualWidth / count) - 20;
+ if (spacing < 2) spacing = 2;
+ DotSpacing = new Thickness(spacing / 2, 0, spacing / 2, 0);
+ }
+ public Dictionary> MusicBeatsDic
+ {
+ get => (Dictionary>)GetValue(MusicBeatsDicProperty);
+ set => SetValue(MusicBeatsDicProperty, value);
+ }
+
+ public static readonly DependencyProperty MusicBeatsDicProperty =
+ DependencyProperty.Register(nameof(MusicBeatsDic), typeof(Dictionary>), typeof(BeatScrollDots),
+ new PropertyMetadata(null, OnMusicBeatsDicChanged));
+
+ private static void OnMusicBeatsDicChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is BeatScrollDots ctrl)
+ {
+ // 可选:根据第一个 key 初始化 DotCount
+ if (ctrl.MusicBeatsDic != null && ctrl.MusicBeatsDic.Any())
+ {
+ int firstKey = ctrl.MusicBeatsDic.Keys.Min();
+ ctrl.DotCount = ctrl.MusicBeatsDic[firstKey].Count;
+ ctrl.UpdateSpacingForCount(ctrl.DotCount);
+ }
+ }
+ }
+ }
+
+ public class DotItem : INotifyPropertyChanged
+ {
+ private bool _isSelected;
+
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set
+ {
+ if (_isSelected != value)
+ {
+ _isSelected = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSelected)));
+ }
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+}
\ No newline at end of file
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml
index 4f558a1..7cfde0b 100644
--- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml
+++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml
@@ -38,9 +38,9 @@
-
-
+
+
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs
index 14c5fe5..4d2df00 100644
--- a/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs
+++ b/Wpf_AiSportsMicrospace/MyUserControl/CoverFlowControl.xaml.cs
@@ -116,7 +116,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
{
if (_currentItem.Progress < 1)
{
- _currentItem.Progress += 0.00556; // 控制速度
+ _currentItem.Progress += 0.01; // 控制速度
if (spark != null)
{
var pos = GetSparkPosition(_currentItem.Progress, 150, 200);
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml b/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml
new file mode 100644
index 0000000..3901272
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml
@@ -0,0 +1,25 @@
+
+
+
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml.cs
new file mode 100644
index 0000000..81435d3
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/WxProgressBar.xaml.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+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.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Wpf_AiSportsMicrospace.MyUserControl
+{
+ ///
+ /// WxProgressBar.xaml 的交互逻辑
+ ///
+ public partial class WxProgressBar : UserControl
+ {
+ public WxProgressBar()
+ {
+ InitializeComponent();
+ this.SizeChanged += WxProgressBar_SizeChanged;
+ }
+
+ private void WxProgressBar_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ UpdateVisual();
+ }
+
+ #region 左右进度属性
+ private double _leftProgress;
+ public double LeftProgress
+ {
+ get => _leftProgress;
+ set
+ {
+ _leftProgress = Clamp(value, 0, 1);
+ _rightProgress = 1 - _leftProgress;
+ UpdateVisual();
+ }
+ }
+
+ private double _rightProgress;
+ public double RightProgress
+ {
+ get => _rightProgress;
+ set
+ {
+ _rightProgress = Clamp(value, 0, 1);
+ _leftProgress = 1 - _rightProgress;
+ UpdateVisual();
+ }
+ }
+ #endregion
+
+ private void UpdateVisual()
+ {
+ double totalWidth = ActualWidth;
+ double totalHeight = ActualHeight;
+ if (totalWidth <= 0 || totalHeight <= 0) return;
+
+ double barHeight = 30; // 进度条高度
+ double middleLineHeight = MiddleLine.Height;
+
+ // 左侧红条
+ LeftBar.Width = totalWidth * _leftProgress;
+ LeftBar.Height = barHeight;
+ Canvas.SetLeft(LeftBar, 0);
+ Canvas.SetTop(LeftBar, (totalHeight - barHeight) / 2);
+
+ // 右侧绿条
+ RightBar.Width = totalWidth * _rightProgress;
+ RightBar.Height = barHeight;
+ Canvas.SetLeft(RightBar, totalWidth - RightBar.Width);
+ Canvas.SetTop(RightBar, (totalHeight - barHeight) / 2);
+
+ // 分割线居中在红绿交界点
+ double middleX = LeftBar.Width - MiddleLine.Width / 2;
+ if (middleX < 0) middleX = 0;
+ if (middleX > totalWidth - MiddleLine.Width) middleX = totalWidth - MiddleLine.Width;
+
+ Canvas.SetLeft(MiddleLine, middleX);
+ Canvas.SetTop(MiddleLine, (totalHeight - middleLineHeight) / 2);
+
+ // 百分比文本居中显示
+ ProgressTextBlock.Text = $"{Math.Round(_leftProgress * 100)}% : {Math.Round(_rightProgress * 100)}%";
+ Canvas.SetLeft(ProgressTextBlock, (totalWidth - ProgressTextBlock.ActualWidth) / 2);
+ Canvas.SetTop(ProgressTextBlock, (totalHeight - ProgressTextBlock.ActualHeight) / 2);
+ }
+
+ private double Clamp(double value, double min, double max) => value < min ? min : value > max ? max : value;
+ }
+}
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/Album/vs.png b/Wpf_AiSportsMicrospace/Resources/Img/Album/vs.png
new file mode 100644
index 0000000..924e879
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/Album/vs.png differ
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs
index 8a549d0..d2f8def 100644
--- a/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/GroupJumpRope.xaml.cs
@@ -216,7 +216,7 @@ namespace Wpf_AiSportsMicrospace.Views
}
}
- private int _currentCountdown = 3;
+ private double _currentCountdown = 3600;
private DateTime _lastUpdateTime = DateTime.Now;
private void StartCountdown(int start = 3)
{
@@ -233,10 +233,10 @@ namespace Wpf_AiSportsMicrospace.Views
private void UpdateCountdown()
{
- if ((DateTime.Now - _lastUpdateTime).TotalSeconds >= 1)
+ if ((DateTime.Now - _lastUpdateTime).TotalMilliseconds >= 600)
{
_lastUpdateTime = DateTime.Now;
- _currentCountdown--;
+ _currentCountdown -= 600;
if (_currentCountdown > 0)
{
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
index 7b9d6a8..1761c7c 100644
--- a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
@@ -35,29 +35,9 @@
TextAlignment="Center"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+