2025-10-20 11:05:31 +08:00

257 lines
9.0 KiB
C#

using 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
{
/// <summary>
/// CoverFlowControl.xaml 的交互逻辑
/// </summary>
/// ST
///
public partial class PopSilder : UserControl
{
//private List<double> _musicBeats = new List<double>()
//{
// 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;
private List<double> _musicBeats;
public bool IsMiss
{
get => _isMiss;
set
{
_isMiss = value;
}
}
public List<double> MusicBeats
{
get => _musicBeats;
set
{
_musicBeats = value;
InitMusicBeats();
}
}
public PopSilder()
{
InitializeComponent();
//InitMusicBeats();
}
private void InitMusicBeats()
{
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) - 650, 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;
miss.Visibility = Visibility.Visible;
head_g.Visibility = Visibility.Hidden;
great.Visibility = Visibility.Hidden;
// 200ms 后隐藏
var hideTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
hideTimer.Start();
hideTimer.Tick += (s, e) =>
{
head_m.Visibility = Visibility.Hidden;
miss.Visibility = Visibility.Hidden;
((DispatcherTimer)s).Stop();
};
}
else
{
head_g.Visibility = Visibility.Visible;
great.Visibility = Visibility.Visible;
head_m.Visibility = Visibility.Hidden;
miss.Visibility = Visibility.Hidden;
// 200ms 后隐藏
var hideTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
hideTimer.Start();
hideTimer.Tick += (s, e) =>
{
_isMiss = true;
head_g.Visibility = Visibility.Hidden;
great.Visibility = Visibility.Hidden;
((DispatcherTimer)s).Stop();
};
}
}
}
public class TimedEventTrigger
{
private DispatcherTimer _timer;
private List<double> _timePoints;
private int _currentIndex;
private DateTime _startTime;
public TimedEventTrigger(List<double> 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<double> TimePointReached;
protected virtual void OnTimePointReached(double timePoint)
{
TimePointReached?.Invoke(timePoint);
}
}
}