This commit is contained in:
tanglong 2026-03-13 13:51:58 +08:00
commit f6c4abec68
12 changed files with 261 additions and 101 deletions

View File

@ -13,7 +13,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
{
public Uri ImageUri { get; set; }
private double _progress;
private double _progress = 0;
private String _progressColor1 = "#e73d42";
public String ProgressColor1
@ -55,7 +55,7 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
}
}
private bool _isSelected;
private bool _isSelected = false;
public bool IsSelected
{
get => _isSelected;

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 195 KiB

View File

@ -51,8 +51,9 @@
HorizontalAlignment="right"
VerticalAlignment="Top"
Width="330"
Height="400"
Height="400"
Margin="0,100,0,0"
MouseDown="GoPro"
/>
<Image
gif:ImageBehavior.AnimatedSource="/Resources/Img/Album/1.gif"
@ -143,7 +144,7 @@
</StackPanel>
<TextBlock Text="基础配置" FontSize="18" Margin="12,30,0,0" FontWeight="Bold" Grid.Row="7"/>
<hc:TextBox hc:InfoElement.TitlePlacement="Left" hc:InfoElement.Title="运动角宽度(米):" Width="400" Text="5" Grid.Row="8" x:Name="homeWidth" />
<hc:TextBox hc:InfoElement.TitlePlacement="Left" hc:InfoElement.Title="多人跳绳点位数量:" Width="400" Text="5" Grid.Row="8" x:Name="homeWidth" />
<TextBlock Text="其他配置" FontSize="18" Margin="12,40,0,0" FontWeight="Bold" Grid.Row="10"/>

View File

@ -50,7 +50,7 @@ namespace Wpf_AiSportsMicrospace
{
ImageUri = GetResourceUri("test_img/test_rope.png"),
ProgressColor1 = "#215bc7",
ProgressColor2 = "#fc640e"
ProgressColor2 = "#fc640e",
});
coverFlow.Images.Add(new CoverFlowItem
{
@ -133,11 +133,20 @@ namespace Wpf_AiSportsMicrospace
}
//测试点击
private void GoNew(object sender, MouseButtonEventArgs e)
private async void GoNew(object sender, MouseButtonEventArgs e)
{
RouterGoNew();
}
private async void GoPro(object sender, MouseButtonEventArgs e)
{
coverFlow.StartSelectedProgress();
Debug.WriteLine("点击进度条");
//await Task.Delay(3000);
//RouterGoNew();
}
//跳转二级页面
private void RouterGoNew()
{

View File

@ -3,6 +3,7 @@ using AiSportsMicrospaceDB.Entities;
using Common;
using Dto;
using Enum;
using HandyControl.Controls;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Concurrent;
@ -74,7 +75,7 @@ namespace Views.JumpLong
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// 播放音乐
PlayMusic("raisehand.mp3");
PlayMusic("jumphand.mp3");
var app = (App)Application.Current;
using var scope = App.AppHost.Services.CreateScope();
@ -121,6 +122,7 @@ namespace Views.JumpLong
int rightWaving = DetectRightHandRaise(humans);
if (rightWaving >= 3 && _sportType == 0) //举手完成 开始跳远检测
{
TipBox.Opacity = 0;
_sportType = 1;
StartSport();
}
@ -193,22 +195,22 @@ namespace Views.JumpLong
};
TipBox.BeginAnimation(UIElement.OpacityProperty, fadeInAnimation);
// 定时移除,并且渐变消失
Task.Delay(duration).ContinueWith(_ =>
{
Dispatcher.Invoke(() =>
{
// 渐变消失动画
var fadeOutAnimation = new DoubleAnimation
{
From = 1,
To = 0,
Duration = TimeSpan.FromSeconds(1.5)
};
TipBox.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
//// 定时移除,并且渐变消失
//Task.Delay(duration).ContinueWith(_ =>
//{
// Dispatcher.Invoke(() =>
// {
// // 渐变消失动画
// var fadeOutAnimation = new DoubleAnimation
// {
// From = 1,
// To = 0,
// Duration = TimeSpan.FromSeconds(1.5)
// };
// TipBox.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
});
});
// });
//});
}
private void MediaPlayer_MediaEnded(object sender, EventArgs e)

View File

@ -50,7 +50,7 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
private GameState _currentGameState = GameState.NotStarted;
private readonly HttpClient _httpClient;
SportOperate sportOperate = new SportOperate();
Image tipImage;
// 容忍时间(节拍误差)
public double _beatTolerance = 0.24; // ±150ms
// 滚动显示的节拍点集合
@ -81,7 +81,7 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
var cfg = await db.GroupPoints.FirstOrDefaultAsync(x => x.Code == AppSettings.Code);
//var pointlist = JsonSerializer.Deserialize<List<(double, double)>>(cfg!.PointsJson);
List<(double XNorm, double YNorm)> pointlist = [(cfg.ControlPoint.X, cfg.ControlPoint.Y), (cfg.Point5.X, cfg.Point5.Y)];
List<(double XNorm, double YNorm)> pointlist = [(cfg.ControlPoint.X, cfg.ControlPoint.Y), (cfg.Point10.X, cfg.Point10.Y)];
_musicJumpRopeContext.UpdateCirclePositions(pointlist);
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
@ -115,7 +115,7 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
}
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,
@ -141,26 +141,26 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
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)
{
@ -235,6 +235,7 @@ namespace Wpf_AiSportsMicrospace.Views.JumpRope
private DateTime _lastUpdateTime = DateTime.Now;
private async void StartCountdown(int start = 4)
{
tipImage.Visibility = Visibility.Hidden;
_mainWin.ShowCountDownAnimation();
_isCountdownStarted = true;
_currentCountdown = start;

View File

@ -44,7 +44,7 @@
</DrawingBrush.Drawing>
</DrawingBrush>
</Canvas.Background>-->
<!-- 动态生成的点位容器 -->
<ItemsControl x:Name="PointsContainer">
<ItemsControl.ItemsPanel>
@ -53,21 +53,21 @@
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!-- 连接线 -->
<Polyline x:Name="ConnectionLine" Stroke="#6366F1"
StrokeDashArray="5,5" Opacity="0.6"/>
<!-- 坐标显示标签 -->
<hc:Tag ShowCloseButton="False" IsSelected="True" x:Name="CoordinateDisplay"
Content="位置点" Padding="18,0" FontSize="14" Visibility="Visible"/>
</Canvas>
<!-- 返回首页按钮 -->
<Button Content="返回首页" Click="Label_MouseDown"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="20" Width="100" Height="30"/>
<!-- 控制面板 -->
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Margin="20" Width="280" Opacity="0.8">
<Border Background="#FFFFFF" Padding="15" CornerRadius="8" Effect="{StaticResource DropShadowEffect}">
@ -75,10 +75,10 @@
<!-- 标题 -->
<TextBlock Text="多人跳绳点配置" FontSize="18" FontWeight="Bold"
Margin="0,0,0,15" HorizontalAlignment="Center"/>
<!-- 分隔线 -->
<Separator Margin="0,0,0,10"/>
<!-- HomeWidth 显示 -->
<!--<TextBlock Text="场地宽度 (HomeWidth):" FontSize="14" Margin="0,5,0,5"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,5">
@ -88,33 +88,33 @@
<TextBlock Text="米" FontSize="14" VerticalAlignment="Center"
Foreground="#6B7280"/>
</StackPanel>-->
<!-- 点位数量显示 -->
<Border Background="#DBEAFE" CornerRadius="4" Margin="0,10,0,10">
<TextBlock x:Name="PointCountText" Text="点位数量: 6 个"
FontSize="16" FontWeight="Bold" Foreground="#1E40AF"
HorizontalAlignment="Center" Padding="10,8"/>
</Border>
<!-- 操作说明 -->
<TextBlock Text="💡 点击点位后可在 Y 轴方向拖动调整"
FontSize="12" Foreground="#6B7280" TextWrapping="Wrap"
Margin="0,10,0,10"/>
<!-- 分隔线 -->
<Separator Margin="0,5,0,10"/>
<!-- 功能按钮 -->
<Button x:Name="LoadPointsButton" Content="📥 加载点数据"
Click="LoadPointsButton_Click"
Margin="0,5" Height="35" Background="#10B981" Foreground="White"
FontSize="14" FontWeight="Bold"/>
<Button x:Name="SavePointsButton" Content="💾 保存点数据"
Click="SavePointsButton_Click"
Margin="0,5" Height="35" Background="#3B82F6" Foreground="White"
FontSize="14" FontWeight="Bold"/>
<Button x:Name="ResetPointsButton" Content="🔄 重置为默认"
Click="ResetPointsButton_Click"
Margin="0,5" Height="35" Background="#EF4444" Foreground="White"
@ -127,6 +127,20 @@
Margin="0,5,0,10">
<ComboBoxItem Content="不设置"/>
</ComboBox>
<!--<TextBlock Text="音乐跳绳一号位:" FontSize="14" Margin="0,10,0,5"/>
<ComboBox x:Name="MusicPointBox"
SelectionChanged="MusicPointBox_SelectionChanged"
Height="32" FontSize="14"
Margin="0,5,0,10">
<ComboBoxItem Content="不设置"/>
</ComboBox>-->
<TextBlock Text="音乐跳绳二号位:" FontSize="14" Margin="0,10,0,5"/>
<ComboBox x:Name="MusicPointBox2"
SelectionChanged="MusicPointBox2_SelectionChanged"
Height="32" FontSize="14"
Margin="0,5,0,10">
<ComboBoxItem Content="不设置"/>
</ComboBox>
<!-- 状态显示 -->
<TextBlock x:Name="StatusText" Text="就绪"
Margin="0,15,0,0" TextWrapping="Wrap"
@ -134,7 +148,7 @@
</StackPanel>
</Border>
</StackPanel>
<!-- 右侧点位数据面板 -->
<Border HorizontalAlignment="Right" VerticalAlignment="Top"
Margin="20,20,320,20" Width="220" Background="White" Opacity="0.8"
@ -144,7 +158,7 @@
<TextBlock Text="点位坐标数据" FontSize="16" FontWeight="Bold"
Margin="0,0,0,10" HorizontalAlignment="Center"/>
<Separator Margin="0,0,0,10"/>
<ItemsControl x:Name="PointsDataList">
<ItemsControl.ItemTemplate>
<DataTemplate>

View File

@ -64,6 +64,12 @@ namespace Wpf_AiSportsMicrospace.Views
/// </summary>
private int _keyPointIndex = 0;
/// <summary>
/// 音乐跳绳二号位索引(0 表示不设置)
/// </summary>
private int _musicPoint2Index = 0;
#endregion
#region 构造函数
@ -132,7 +138,8 @@ namespace Wpf_AiSportsMicrospace.Views
}
_homeWidth = baseConfig.HomeWidth;
int pointCount = CalculatePointCount(_homeWidth);
//int pointCount = CalculatePointCount(_homeWidth);
int pointCount = (int)(_homeWidth);
// 更新 UI 显示
//HomeWidthText.Text = _homeWidth.ToString("F1");
@ -311,6 +318,36 @@ namespace Wpf_AiSportsMicrospace.Views
_keyPointIndex = 0;
}
// 加载音乐跳绳二号位位置(从 Point10 字段),并与点位列表对比
var point10Property = typeof(GroupPoints).GetProperty("Point10");
if (point10Property != null)
{
var dbPoint10 = point10Property.GetValue(data);
if (dbPoint10 != null)
{
var xProp = dbPoint10.GetType().GetProperty("X");
var yProp = dbPoint10.GetType().GetProperty("Y");
if (xProp != null && yProp != null)
{
var point10X = (double)(xProp.GetValue(dbPoint10) ?? 0);
var point10Y = (double)(yProp.GetValue(dbPoint10) ?? 0);
// 与点位列表对比,找出匹配的点位
double tolerance = 1.0; // 容差值,允许1像素的误差
foreach (var point in _points)
{
if (Math.Abs(point.X - point10X) < tolerance &&
Math.Abs(point.Y - point10Y) < tolerance)
{
_musicPoint2Index = point.Id;
UpdateStatus($"音乐跳绳二号位已识别为点位 {point.Id}: X:{point10X:F0} Y:{point10Y:F0}");
break;
}
}
}
}
}
RefreshPointsDataList();
UpdateConnectionLine();
@ -511,27 +548,29 @@ namespace Wpf_AiSportsMicrospace.Views
{
// 保存当前选择
int previousSelection = KeyPointComboBox.SelectedIndex;
int previousSelection2 = MusicPointBox2.SelectedIndex;
// 清除并重新填充选项
KeyPointComboBox.Items.Clear();
MusicPointBox2.Items.Clear();
// 添加"不设置"选项
var noneItem = new ComboBoxItem
{
Content = "不设置",
Tag = 0
};
KeyPointComboBox.Items.Add(noneItem);
// 为每个 ComboBox 创建独立的 "不设置" 选项
var noneItem1 = new ComboBoxItem { Content = "不设置", Tag = 0 };
var noneItem2 = new ComboBoxItem { Content = "不设置", Tag = 0 };
var noneItem3 = new ComboBoxItem { Content = "不设置", Tag = 0 };
// 添加所有点位选项
KeyPointComboBox.Items.Add(noneItem1);
MusicPointBox2.Items.Add(noneItem3);
// 添加所有点位选项(为每个 ComboBox 创建独立实例)
foreach (var point in _points)
{
var item = new ComboBoxItem
{
Content = $"点位 {point.Id}",
Tag = point.Id
};
KeyPointComboBox.Items.Add(item);
var item1 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
var item2 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
var item3 = new ComboBoxItem { Content = $"点位 {point.Id}", Tag = point.Id };
KeyPointComboBox.Items.Add(item1);
MusicPointBox2.Items.Add(item3);
}
// 恢复选择或默认选择
@ -556,8 +595,32 @@ namespace Wpf_AiSportsMicrospace.Views
{
KeyPointComboBox.SelectedIndex = 0;
}
}
// 恢复音乐跳绳二号位选择
if (previousSelection2 > 0 && previousSelection2 <= _points.Count)
{
MusicPointBox2.SelectedIndex = previousSelection2;
}
else if (_musicPoint2Index > 0)
{
int comboIndex = _points.FindIndex(p => p.Id == _musicPoint2Index);
if (comboIndex >= 0)
{
MusicPointBox2.SelectedIndex = comboIndex + 1;
}
else
{
MusicPointBox2.SelectedIndex = 0;
}
}
else
{
MusicPointBox2.SelectedIndex = 0;
}
}
/// <summary>
/// 控制点位选择改变事件
/// </summary>
@ -580,6 +643,28 @@ namespace Wpf_AiSportsMicrospace.Views
}
}
/// <summary>
/// 音乐跳绳二号位选择改变事件
/// </summary>
private void MusicPointBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (MusicPointBox2.SelectedItem is ComboBoxItem selectedItem)
{
_musicPoint2Index = (int)(selectedItem.Tag ?? 0);
if (_musicPoint2Index > 0)
{
UpdateStatus($"已设置点位 {_musicPoint2Index} 为音乐跳绳二号位");
HighlightMusicPoint2(_musicPoint2Index);
}
else
{
UpdateStatus("已取消音乐跳绳二号位设置");
ResetAllPointsHighlight();
}
}
}
/// <summary>
/// 高亮显示控制点位
/// </summary>
@ -610,6 +695,36 @@ namespace Wpf_AiSportsMicrospace.Views
}
}
/// <summary>
/// 高亮显示音乐跳绳二号位
/// </summary>
private void HighlightMusicPoint2(int pointId)
{
// 重置所有点位样式
ResetAllPointsHighlight();
// 高亮音乐跳绳二号位(使用紫色区分)
var ellipse = MainCanvas.Children
.OfType<Ellipse>()
.FirstOrDefault(e => e.Name == $"PointEllipse_{pointId}");
if (ellipse != null)
{
ellipse.Fill = new LinearGradientBrush
{
StartPoint = new Point(0.5, 0),
EndPoint = new Point(0.5, 1),
GradientStops = new GradientStopCollection
{
new GradientStop((Color)ColorConverter.ConvertFromString("#8B5CF6"), 0),
new GradientStop((Color)ColorConverter.ConvertFromString("#7C3AED"), 1)
}
};
ellipse.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#6D28D9"));
ellipse.StrokeThickness = 3;
}
}
/// <summary>
/// 重置所有点位的高亮样式
/// </summary>
@ -1126,6 +1241,21 @@ namespace Wpf_AiSportsMicrospace.Views
controlPoint.SetValue(pointsData, controlPointNew);
}
// 保存音乐跳绳二号位位置到 Point10 字段
if (_musicPoint2Index > 0 && _musicPoint2Index <= _points.Count)
{
var point10Property = typeof(GroupPoints).GetProperty("Point10");
if (point10Property != null)
{
var musicPoint2New = new AiSportsMicrospaceDB.Entities.Point
{
X = _points[_musicPoint2Index - 1].X,
Y = _points[_musicPoint2Index - 1].Y
};
point10Property.SetValue(pointsData, musicPoint2New);
}
}
db.SaveChanges();
UpdateStatus("点数据保存成功");
}

View File

@ -45,6 +45,7 @@ namespace Views.SquatFu
private readonly object _updateLock = new object();
private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>();
private WhackAMoleContext _WhackAMoleContext;
Image tipImage;
public WhackAMole()
{
@ -117,7 +118,7 @@ namespace Views.SquatFu
}
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,
@ -143,29 +144,29 @@ namespace Views.SquatFu
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);
//_isCountdownStarted = true;
//FinishCountdown();
//_currentGameState = GameState.Running;
//Task.Delay(duration).ContinueWith(_ =>
//{
// Dispatcher.Invoke(() =>
// {
// // 渐变消失动画
// var fadeOutAnimation = new DoubleAnimation
// {
// From = 1,
// To = 0,
// Duration = TimeSpan.FromSeconds(1.5)
// };
// tipImage.BeginAnimation(UIElement.OpacityProperty, fadeOutAnimation);
// //_isCountdownStarted = true;
// //FinishCountdown();
// //_currentGameState = GameState.Running;
// 完成后移除图片
fadeOutAnimation.Completed += (s, e) =>
{
userListBox.Children.Remove(tipImage);
};
});
});
// // 完成后移除图片
// fadeOutAnimation.Completed += (s, e) =>
// {
// userListBox.Children.Remove(tipImage);
// };
// });
//});
}
private void MediaPlayer_MediaEnded(object sender, EventArgs e)
@ -250,6 +251,7 @@ namespace Views.SquatFu
private DateTime _lastUpdateTime = DateTime.Now;
private async void StartCountdown(int start = 3)
{
tipImage.Visibility = Visibility.Collapsed; // 隐藏提示图片
_currentGameState = GameState.Running;
_mainWin.ShowCountDownAnimation();

View File

@ -120,6 +120,7 @@
<None Remove="Resources\Music\countdown_3.mp3" />
<None Remove="Resources\Music\homeprojectselected.mp3" />
<None Remove="Resources\Music\homeprojectselected1.mp3" />
<None Remove="Resources\Music\jumphand.mp3" />
<None Remove="Resources\Music\musicjumprope.mp3" />
<None Remove="Resources\Music\musicjumprope1.mp3" />
<None Remove="Resources\Music\raisehand.mp3" />
@ -129,9 +130,6 @@
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\app.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
@ -515,6 +513,9 @@
<Resource Include="Resources\Music\homeprojectselected1.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
<Resource Include="Resources\Music\jumphand.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
<Resource Include="Resources\Music\musicjumprope.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 195 KiB