diff --git a/Wpf_AiSportsMicrospace/MyUserControl/ImageStateToVisibilityConverter.cs b/Wpf_AiSportsMicrospace/MyUserControl/ImageStateToVisibilityConverter.cs
index 0fc8476..ee4c005 100644
--- a/Wpf_AiSportsMicrospace/MyUserControl/ImageStateToVisibilityConverter.cs
+++ b/Wpf_AiSportsMicrospace/MyUserControl/ImageStateToVisibilityConverter.cs
@@ -2,6 +2,7 @@ using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
+using System.Windows.Media.Animation;
namespace Wpf_AiSportsMicrospace.MyUserControl
{
@@ -21,4 +22,137 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
throw new NotImplementedException();
}
}
+
+ public class MarginAnimationController
+ {
+ private Storyboard _storyboard;
+ private FrameworkElement _targetElement;
+ private ThicknessAnimation _thicknessAnimation;
+
+ ///
+ /// 初始化动画控制器
+ ///
+ /// 目标UI元素
+ public MarginAnimationController(FrameworkElement targetElement)
+ {
+ _targetElement = targetElement;
+ InitializeAnimation();
+ }
+
+ private void InitializeAnimation()
+ {
+ // 创建厚度动画
+ _thicknessAnimation = new ThicknessAnimation
+ {
+ Duration = TimeSpan.FromSeconds(1),
+ FillBehavior = FillBehavior.HoldEnd
+ };
+
+ // 创建故事板
+ _storyboard = new Storyboard();
+ _storyboard.Children.Add(_thicknessAnimation);
+
+ // 设置目标属性和目标对象
+ Storyboard.SetTarget(_thicknessAnimation, _targetElement);
+ Storyboard.SetTargetProperty(_thicknessAnimation, new PropertyPath(FrameworkElement.MarginProperty));
+ }
+
+ ///
+ /// 开始动画
+ ///
+ /// 目标边距
+ /// 动画时长(毫秒)
+ /// 缓动函数
+ public void StartAnimation(Thickness targetMargin, int durationMs = 1000, IEasingFunction easingFunction = null)
+ {
+ // 设置动画参数
+ _thicknessAnimation.To = targetMargin;
+ _thicknessAnimation.Duration = TimeSpan.FromMilliseconds(durationMs);
+
+ if (easingFunction != null)
+ {
+ _thicknessAnimation.EasingFunction = easingFunction;
+ }
+
+ // 开始动画
+ _storyboard.Begin();
+ }
+
+ ///
+ /// 开始从当前值到目标值的动画
+ ///
+ public void StartAnimationFromCurrent(Thickness targetMargin, int durationMs = 1000)
+ {
+ _thicknessAnimation.From = null; // 从当前值开始
+ _thicknessAnimation.To = targetMargin;
+ _thicknessAnimation.Duration = TimeSpan.FromMilliseconds(durationMs);
+
+ _storyboard.Begin();
+ }
+
+ ///
+ /// 开始从指定值到目标值的动画
+ ///
+ public void StartAnimationFromTo(Thickness fromMargin, Thickness toMargin, int durationMs = 1000)
+ {
+ _thicknessAnimation.From = fromMargin;
+ _thicknessAnimation.To = toMargin;
+ _thicknessAnimation.Duration = TimeSpan.FromMilliseconds(durationMs);
+
+ _storyboard.Begin();
+ }
+
+ ///
+ /// 停止动画
+ ///
+ public void StopAnimation()
+ {
+ _storyboard.Stop();
+ }
+
+ ///
+ /// 暂停动画
+ ///
+ public void PauseAnimation()
+ {
+ _storyboard.Pause();
+ }
+
+ ///
+ /// 恢复动画
+ ///
+ public void ResumeAnimation()
+ {
+ _storyboard.Resume();
+ }
+
+ ///
+ /// 设置动画完成回调
+ ///
+ public void SetCompletedCallback(EventHandler callback)
+ {
+ _storyboard.Completed += callback;
+ }
+
+ ///
+ /// 移除动画完成回调
+ ///
+ public void RemoveCompletedCallback(EventHandler callback)
+ {
+ _storyboard.Completed -= callback;
+ }
+
+ ///
+ /// 检查动画是否正在运行
+ ///
+ public bool IsAnimating => _storyboard.GetCurrentState() == ClockState.Active;
+
+ ///
+ /// 设置缓动函数
+ ///
+ public void SetEasingFunction(IEasingFunction easingFunction)
+ {
+ _thicknessAnimation.EasingFunction = easingFunction;
+ }
+ }
}
\ No newline at end of file
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml b/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml
new file mode 100644
index 0000000..def6c5c
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml
@@ -0,0 +1,39 @@
+锘
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml.cs b/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml.cs
new file mode 100644
index 0000000..be5490b
--- /dev/null
+++ b/Wpf_AiSportsMicrospace/MyUserControl/PopSilder.xaml.cs
@@ -0,0 +1,230 @@
+锘縰sing HandyControl.Controls;
+using SharpDX.Direct3D9;
+using System;
+using System.Collections.Generic;
+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;
+using WpfAnimatedGif;
+
+namespace Wpf_AiSportsMicrospace.MyUserControl
+{
+ ///
+ /// CoverFlowControl.xaml 鐨勪氦浜掗昏緫
+ ///
+ /// ST
+ ///
+ public partial class PopSilder : UserControl
+ {
+
+ private List _musicBeats = new List()
+ {
+ 0.545,1.09,1.635,2.18,2.725,3.27,3.815,4.36,4.905,5.45,
+ 5.995,6.54,7.085,7.63,8.175,8.72,9.265,9.81,10.355,10.9,
+ //11.445,11.99,12.535,13.08,13.625,14.17,14.715,15.26,15.805,16.35,
+ //16.895,17.44,17.985,18.53,19.075,19.62,20.165,20.71,21.255,21.8,
+ //22.345,22.89,23.435,23.98,24.525,25.07,25.615,26.16,26.705,27.25,
+ //27.795,28.34,28.885,29.43,29.975,30.52,31.065,31.61,32.155,32.7,
+ //33.245,33.79,34.335,34.88,35.425,35.97,36.515,37.06,37.605,38.15,
+ //38.695,39.24,39.785,40.33,40.875,41.42,41.965,42.51,43.055,43.6,
+ //44.145,44.69,45.235,45.78,46.325,46.87,47.415,47.96,48.505,49.05,
+ //49.595,50.14,50.685,51.23,51.775,52.32,52.865,53.41,53.955,54.5,
+ //55.045,55.59,56.135,56.68,57.225,57.77,58.315,58.86,59.405,59.95,
+ //60.495,61.04,61.585,62.13,62.675,63.22,63.765,64.31,64.855,65.4,
+ //65.945,66.49,67.035,67.58,68.125,68.67,69.215,69.76,70.305,70.85,
+ //71.395,71.94,72.485,73.03,73.575,74.12,74.665,75.21,75.755,76.3,
+ //76.845,77.39,77.935,78.48,79.025,79.57,80.115,80.66,81.205,81.75,
+ //82.295,82.84,83.385,83.93,84.475,85.02,85.565,86.11,86.655,87.2,
+ //87.745,88.29,88.835,89.38,89.925,90.47,91.015,91.56,92.105,92.65,
+ //93.195,93.74,94.285,94.83,95.375,95.92,96.465,97.01,97.555,98.1,
+ //98.645,99.19,99.735,100.28,100.825,101.37,101.915,102.46,103.005,103.55,
+ //104.095,104.64,105.185,105.73,106.275,106.82,107.365,107.91,108.455
+ };
+ private Storyboard _marginStoryboard;
+ private ThicknessAnimation _marginAnimation;
+ private TimedEventTrigger _trigger;
+ private bool _isMiss = true;
+ public bool IsMiss
+ {
+ get => _isMiss;
+ set
+ {
+ _isMiss = value;
+ }
+ }
+ public PopSilder()
+ {
+ InitializeComponent();
+ double time = Math.Floor(_musicBeats[_musicBeats.Count - 1]);
+ double startMargin = _musicBeats[0] * 200;
+ ani.Margin = new Thickness(startMargin, 0, 0, 0);
+ for (int i = 1; i < _musicBeats.Count + 1; i++)
+ {
+ double width = i != _musicBeats.Count ? (_musicBeats[i] - _musicBeats[i - 1]) * 200 : 0;
+ var img = new Image
+ {
+ Width = 52,
+ Height = 50,
+ Source = new BitmapImage(new Uri("pack://application:,,,/Resources/Img/play_img/music_rope/point.png")),
+ };
+ var grid = new StackPanel
+ {
+ Width = width,
+ Height = 5,
+ Background = new SolidColorBrush(Color.FromRgb(0, 0, 0))
+ };
+
+ var StackPanel = new StackPanel { Orientation = Orientation.Horizontal };
+ StackPanel.Children.Add(img);
+ StackPanel.Children.Add(grid);
+ ani.Children.Add(StackPanel);
+ }
+ }
+
+
+ private void InitializeMarginAnimation()
+ {
+ double time = Math.Floor(_musicBeats[_musicBeats.Count - 1]) + 1;
+ double startMargin = _musicBeats[0] * 200;
+ // 鍒涘缓鍘氬害鍔ㄧ敾
+ _marginAnimation = new ThicknessAnimation
+ {
+ From = new Thickness(startMargin, 0, 0, 0), // 璧峰鍊
+ To = new Thickness(-time * (200 + 52) - 350, 0, 0, 0), // 鐩爣鍊
+ Duration = TimeSpan.FromSeconds(time), // time绉掓寔缁椂闂
+ FillBehavior = FillBehavior.HoldEnd // 鍔ㄧ敾瀹屾垚鍚庝繚鎸佺姸鎬
+ };
+ Console.WriteLine("ani.Width:" + ani.Width);
+ // 鍒涘缓鏁呬簨鏉
+ _marginStoryboard = new Storyboard();
+ _marginStoryboard.Children.Add(_marginAnimation);
+
+ // 璁剧疆鐩爣瀵硅薄鍜屽睘鎬
+ Storyboard.SetTarget(_marginAnimation, ani);
+ Storyboard.SetTargetProperty(_marginAnimation, new PropertyPath(StackPanel.MarginProperty));
+
+
+ _trigger = new TimedEventTrigger(_musicBeats);
+ _trigger.TimePointReached += OnTimePointReached;
+ }
+
+ // 榧犳爣鐐瑰嚮浜嬩欢 - 寮濮嬪姩鐢
+ private void ani_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ StartMarginAnimation();
+ }
+
+ public void StartMarginAnimation()
+ {
+ InitializeMarginAnimation();
+ _marginStoryboard?.Begin();
+ _trigger.Start();
+ }
+
+ public void StopMarginAnimation()
+ {
+ _marginStoryboard?.Stop();
+ _trigger.Stop();
+ }
+
+
+ private void OnTimePointReached(double timePoint)
+ {
+ Console.WriteLine($"瑙﹀彂鏃堕棿鐐: {timePoint}");
+ if (_isMiss)
+ {
+ head_m.Visibility = Visibility.Visible;
+ //200ms鍚庨殣钘
+ var hideTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
+ hideTimer.Tick += (s, e) =>
+ {
+ head_m.Visibility = Visibility.Hidden;
+ _isMiss = true;
+ hideTimer.Stop();
+ };
+ }
+ else
+ {
+ head_g.Visibility = Visibility.Visible;
+ //200ms鍚庨殣钘
+ var hideTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
+ hideTimer.Tick += (s, e) =>
+ {
+ head_g.Visibility = Visibility.Hidden;
+ _isMiss = false;
+ hideTimer.Stop();
+ };
+ }
+ }
+ }
+
+ public class TimedEventTrigger
+ {
+ private DispatcherTimer _timer;
+ private List _timePoints;
+ private int _currentIndex;
+ private DateTime _startTime;
+
+ public TimedEventTrigger(List timePoints)
+ {
+ _timePoints = timePoints;
+ _currentIndex = 0;
+
+ _timer = new DispatcherTimer();
+ _timer.Interval = TimeSpan.FromMilliseconds(10); // 10ms绮惧害
+ _timer.Tick += CheckTimePoint;
+ }
+
+ public void Start()
+ {
+ _startTime = DateTime.Now;
+ _timer.Start();
+ }
+
+ public void Stop()
+ {
+ _timer.Stop();
+ }
+
+ private void CheckTimePoint(object sender, EventArgs e)
+ {
+ double elapsedSeconds = (DateTime.Now - _startTime).TotalSeconds;
+
+ // 妫鏌ユ槸鍚﹀埌杈句笅涓涓椂闂寸偣
+ if (_currentIndex < _timePoints.Count &&
+ elapsedSeconds >= _timePoints[_currentIndex])
+ {
+ // 瑙﹀彂浜嬩欢
+ OnTimePointReached(_timePoints[_currentIndex]);
+ _currentIndex++;
+ }
+
+ // 鎵鏈夋椂闂寸偣閮藉鐞嗗畬姣曪紝鍋滄璁℃椂鍣
+ if (_currentIndex >= _timePoints.Count)
+ {
+ _timer.Stop();
+ }
+ }
+
+ public event Action TimePointReached;
+
+ protected virtual void OnTimePointReached(double timePoint)
+ {
+ TimePointReached?.Invoke(timePoint);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great-p.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great-p.png
new file mode 100644
index 0000000..ee8e9d1
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great-p.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great.png
new file mode 100644
index 0000000..975533b
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/great.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_g.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_g.png
new file mode 100644
index 0000000..b7788b6
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_g.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_m.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_m.png
new file mode 100644
index 0000000..5a2f009
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/head_m.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/miss.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/miss.png
new file mode 100644
index 0000000..91ed76d
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/miss.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/play_bg.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/play_bg.png
new file mode 100644
index 0000000..a464956
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/play_bg.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/point.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/point.png
new file mode 100644
index 0000000..2dbebed
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/point.png differ
diff --git a/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/title.png b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/title.png
new file mode 100644
index 0000000..0261698
Binary files /dev/null and b/Wpf_AiSportsMicrospace/Resources/Img/play_img/music_rope/title.png differ
diff --git a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
index 52d3bf4..7b9d6a8 100644
--- a/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
+++ b/Wpf_AiSportsMicrospace/Views/JumpRope/MusicJumpRope.xaml
@@ -8,14 +8,14 @@
Height="1080" Width="1920" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded">
-
+
@@ -58,5 +58,23 @@
+
+
+
diff --git a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj
index 50a781f..7b7877b 100644
--- a/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj
+++ b/Wpf_AiSportsMicrospace/Wpf_AiSportsMicrospace.csproj
@@ -42,6 +42,14 @@
+
+
+
+
+
+
+
+
@@ -77,6 +85,24 @@
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
@@ -215,6 +241,15 @@
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always