601 lines
23 KiB
C#
601 lines
23 KiB
C#
using AiSportsMicrospaceDB.DBContext;
|
||
using Common;
|
||
using Dto;
|
||
using Enum;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using SportExpand;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Net.Http;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
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 Wpf_AiSportsMicrospace.Common;
|
||
using Wpf_AiSportsMicrospace.Dto;
|
||
using Wpf_AiSportsMicrospace.Enum;
|
||
using Wpf_AiSportsMicrospace.MyUserControl;
|
||
using Wpf_AiSportsMicrospace.Views;
|
||
using WpfAnimatedGif;
|
||
using Yztob.AiSports.Inferences.Things;
|
||
using Yztob.AiSports.Postures;
|
||
using Yztob.AiSports.Postures.Sports;
|
||
using Yztob.AiSports.Sensors.Things;
|
||
|
||
namespace Wpf_AiSportsMicrospace.Views.JumpRope
|
||
{
|
||
/// <summary>
|
||
/// MusicJumpRope.xaml 的交互逻辑
|
||
/// </summary>
|
||
public partial class MusicJumpRope : UserControl
|
||
{
|
||
private Main _mainWin => Application.Current.MainWindow as Main;
|
||
private MediaPlayer _mediaPlayer = new MediaPlayer();
|
||
private readonly object _updateLock = new object();
|
||
private readonly Dictionary<int, (string lastNumber, DateTime lastChangeTime, string currentState)> _jumpStatus = new Dictionary<int, (string, DateTime, string)>();
|
||
private MusicJumpRopeContext _musicJumpRopeContext;
|
||
private GameState _currentGameState = GameState.NotStarted;
|
||
private readonly HttpClient _httpClient;
|
||
SportOperate sportOperate = new SportOperate();
|
||
|
||
// 容忍时间(节拍误差)
|
||
public double _beatTolerance = 0.24; // ±150ms
|
||
// 滚动显示的节拍点集合
|
||
public ObservableCollection<BeatItem> BeatDisplayLeft { get; set; } = new();
|
||
public ObservableCollection<BeatItem> BeatDisplayRight { get; set; } = new();
|
||
|
||
public MusicJumpRope()
|
||
{
|
||
InitializeComponent();
|
||
Loaded += UserControl_Loaded;
|
||
Unloaded += UserControl_Unloaded;
|
||
_musicJumpRopeContext = new MusicJumpRopeContext();
|
||
}
|
||
|
||
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||
{
|
||
DrawCirclesWithText();
|
||
// 播放音乐
|
||
PlayMusic("raisehand.mp3");
|
||
PkBar.LeftProgress = 0.5;
|
||
|
||
popSilder1.MusicBeats = _musicJumpRopeContext.MusicBeats["1"];
|
||
popSilder2.MusicBeats = _musicJumpRopeContext.MusicBeats["1"];
|
||
|
||
var app = (App)Application.Current;
|
||
using var scope = App.AppHost.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
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.Point3.X, cfg.Point3.Y)];
|
||
_musicJumpRopeContext.UpdateCirclePositions(pointlist);
|
||
|
||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||
}
|
||
|
||
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
|
||
{
|
||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||
}
|
||
private void PlayMusic(string musicFileName)
|
||
{
|
||
// 获取项目根目录
|
||
string projectRoot = System.IO.Path.Combine(AppContext.BaseDirectory, @"..\..\..");
|
||
string musicPath = System.IO.Path.Combine(projectRoot, "Resources", "Music", musicFileName);
|
||
string imgPath = System.IO.Path.Combine(projectRoot, "Resources", "Img", "提示图.png");
|
||
|
||
if (!File.Exists(musicPath))
|
||
{
|
||
Console.WriteLine($"音乐文件不存在: {musicPath}");
|
||
return;
|
||
}
|
||
|
||
_mediaPlayer.Open(new Uri(musicPath, UriKind.Absolute));
|
||
|
||
ShowCenterTip(imgPath, TimeSpan.FromSeconds(3));
|
||
|
||
// 监听播放完成事件
|
||
_mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
|
||
|
||
_mediaPlayer.Play();
|
||
}
|
||
private void ShowCenterTip(string imagePath, TimeSpan duration)
|
||
{
|
||
var 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),
|
||
};
|
||
|
||
// 增加图片的大小,调整比例
|
||
tipImage.Width = 1920 * 0.9; // 宽度为 Canvas 宽度的 90%
|
||
tipImage.Height = 1080 * 0.6; // 高度为 Canvas 高度的 60%
|
||
|
||
// 将图片添加到 Overlay Canvas
|
||
userBox.Children.Add(tipImage);
|
||
|
||
// 渐变出现动画
|
||
var fadeInAnimation = new DoubleAnimation
|
||
{
|
||
From = 0,
|
||
To = 1,
|
||
Duration = TimeSpan.FromSeconds(1.5)
|
||
};
|
||
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);
|
||
|
||
// 完成后移除图片
|
||
fadeOutAnimation.Completed += (s, e) =>
|
||
{
|
||
userBox.Children.Remove(tipImage);
|
||
};
|
||
});
|
||
});
|
||
}
|
||
private void MediaPlayer_MediaEnded(object sender, EventArgs e)
|
||
{
|
||
// 音乐播放完成后的逻辑
|
||
Console.WriteLine("音乐播放完成!");
|
||
|
||
// 可在这里绑定抽帧事件
|
||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||
}
|
||
private bool _isCountdownStarted = false; // 新增标记
|
||
private void OnHumanFrameUpdated(object sender, List<Human> humans)
|
||
{
|
||
try
|
||
{
|
||
if (humans == null || humans.Count == 0) return;
|
||
|
||
switch (_currentGameState)
|
||
{
|
||
case GameState.NotStarted:
|
||
if (!_isCountdownStarted)
|
||
{
|
||
int leftWaving = sportOperate.VerifyLeftWavingAction(humans);
|
||
if (leftWaving == 5)
|
||
{
|
||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||
_mainWin.WebcamClient.StopExtract();
|
||
|
||
// 举左手逻辑,例如结束动画或退出
|
||
var newPage = new Home();
|
||
_mainWin?.SwitchPageWithMaskAnimation(newPage, true);
|
||
return; // 提前退出
|
||
}
|
||
}
|
||
|
||
int rightWaving = sportOperate.VerifyRightWavingAction(humans);
|
||
if (rightWaving >= 3 && RankingGrid.Visibility != Visibility.Visible)
|
||
{
|
||
switch (rightWaving)
|
||
{
|
||
case (int)WavingAction.FirstHand:
|
||
StartCountdown(3);
|
||
_isCountdownStarted = true;
|
||
break;
|
||
case (int)WavingAction.Raising:
|
||
UpdateCountdown();
|
||
break;
|
||
case (int)WavingAction.RaiseHand:
|
||
FinishCountdown();
|
||
_currentGameState = GameState.Running;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case GameState.Running:
|
||
UpdateCircleCounts(humans);
|
||
break;
|
||
}
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine("OnFrameExtracted error: " + ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
private int _currentCountdown = 3;
|
||
private DateTime _lastUpdateTime = DateTime.Now;
|
||
private void StartCountdown(int start = 4)
|
||
{
|
||
_currentCountdown = start;
|
||
//countdownText.Text = _currentCountdown.ToString();
|
||
//countdownGrid.Visibility = Visibility.Visible;
|
||
_lastUpdateTime = DateTime.Now;
|
||
_mainWin.ShowCountDownAnimation();
|
||
Utils.PlayBackgroundMusic("countdown_3.mp3", false);
|
||
|
||
//开始人脸识别=============================================
|
||
Action<VideoFrame> handler = null;
|
||
|
||
handler = async (frame) =>
|
||
{
|
||
double[] xValues = [.. _musicJumpRopeContext.CirclePositions.Select(p => p.XNorm)];
|
||
var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||
var studentList = Utils.FacialRecognition(buffer, xValues);
|
||
|
||
if (studentList != null && studentList.Count > 0)
|
||
{
|
||
// 解绑事件
|
||
_mainWin.FacialRecognitionEvent -= handler;
|
||
name1.Text = studentList[0]?.StudentName ?? "一号玩家";
|
||
name2.Text = studentList[1]?.StudentName ?? "二号玩家";
|
||
if (studentList.Count > 1 && studentList[0].Photo != "")
|
||
{
|
||
await LoadImageFromUrlAsync(studentList[0]?.Photo ?? "", avatar1);
|
||
}
|
||
if (studentList.Count > 2 && studentList[1].Photo != "")
|
||
{
|
||
await LoadImageFromUrlAsync(studentList[1]?.Photo ?? "", avatar2);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
// 这里可以继续处理 studentList
|
||
};
|
||
|
||
// 绑定事件
|
||
_mainWin.FacialRecognitionEvent += handler;
|
||
}
|
||
|
||
private async Task LoadImageFromUrlAsync(string imageUrl, Image image)
|
||
{
|
||
try
|
||
{
|
||
// 异步下载图片数据
|
||
byte[] imageData = await _httpClient.GetByteArrayAsync(imageUrl);
|
||
|
||
// 创建BitmapImage并设置源
|
||
var bitmap = new BitmapImage();
|
||
using (var stream = new MemoryStream(imageData))
|
||
{
|
||
bitmap.BeginInit();
|
||
bitmap.CacheOption = BitmapCacheOption.OnLoad; // 图片加载后缓存到内存
|
||
bitmap.StreamSource = stream;
|
||
bitmap.EndInit(); // 确保EndInit,否则可能导致图片加载不完整
|
||
}
|
||
bitmap.Freeze(); // 跨线程访问时可选
|
||
|
||
// 在UI线程上设置Image控件的Source
|
||
image.Source = bitmap;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 处理异常(例如,网络错误、URL无效、图片格式不支持等)
|
||
//MessageBox.Show($"加载图片失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void UpdateCountdown()
|
||
{
|
||
if ((DateTime.Now - _lastUpdateTime).TotalSeconds >= 1)
|
||
{
|
||
_lastUpdateTime = DateTime.Now;
|
||
_currentCountdown--;
|
||
|
||
if (_currentCountdown > 0)
|
||
{
|
||
countdownText.Text = _currentCountdown.ToString();
|
||
}
|
||
else
|
||
{
|
||
FinishCountdown();
|
||
}
|
||
}
|
||
}
|
||
|
||
private async void FinishCountdown()
|
||
{
|
||
countdownText.Text = "GO!";
|
||
countdownGrid.Visibility = Visibility.Hidden;
|
||
// 启动60秒倒计时(独立任务)
|
||
StartGameCountdown(108);
|
||
ShowMusicAnimation();
|
||
}
|
||
|
||
private async void StartGameCountdown(int seconds)
|
||
{
|
||
//_musicCurrentTime = Utils.GetMusicTotalDuration();
|
||
|
||
countdownGrid.Visibility = Visibility.Visible;
|
||
|
||
// 播放背景音乐(循环)
|
||
Utils.PlayBackgroundMusic("1.MP3", true);
|
||
|
||
popSilder1.StartMarginAnimation();
|
||
popSilder2.StartMarginAnimation();
|
||
|
||
for (int i = seconds; i >= 0; i--)
|
||
{
|
||
countdownText.Text = i.ToString();
|
||
await Task.Delay(1000);
|
||
}
|
||
|
||
// 停止音乐
|
||
Utils.StopBackgroundMusic();
|
||
// 停止实时检测和视频流
|
||
|
||
countdownGrid.Visibility = Visibility.Hidden;
|
||
_mainWin.HumanFrameUpdated -= OnHumanFrameUpdated;
|
||
_mainWin.WebcamClient.StopExtract();
|
||
|
||
// 计算排名
|
||
var rankList = _musicJumpRopeContext.UpdateRankList();
|
||
var scoreList = _musicJumpRopeContext.UpdateScoreRankList();
|
||
|
||
|
||
// 更新游戏状态
|
||
_currentGameState = GameState.NotStarted;
|
||
_isCountdownStarted = false;
|
||
|
||
// 恢复视频流
|
||
Application.Current.Dispatcher.Invoke(() =>
|
||
{
|
||
_mainWin.HumanFrameUpdated += OnHumanFrameUpdated;
|
||
_mainWin.WebcamClient.StartExtract();
|
||
showRank();
|
||
// 更新 UI(排行榜或分数板)
|
||
// ShowRankingBoard(rankList);
|
||
});
|
||
}
|
||
|
||
public void showRank()
|
||
{
|
||
double left = _musicJumpRopeContext.UserBeatSyncList[0];
|
||
double right = _musicJumpRopeContext.UserBeatSyncList[1];
|
||
score4.Text = (left * 10).ToString();
|
||
score3.Text = (right * 10).ToString();
|
||
if (left > right)
|
||
{
|
||
lose1.Margin = new Thickness(60, 0, 0, 0);
|
||
lose2.Margin = new Thickness(60, 0, 0, 0);
|
||
lose3.Margin = new Thickness(60, 0, 0, 0);
|
||
win1.Margin = new Thickness(980, -123, 0, 0);
|
||
win2.Margin = new Thickness(980, -123, 0, 0);
|
||
|
||
text1.Text = "LOSE";
|
||
text2.Text = "WIN";
|
||
text1.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#7987a2"));
|
||
text2.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#fdcb50"));
|
||
}
|
||
else if (right == left)
|
||
{
|
||
text2.Text = "WIN";
|
||
text2.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#fdcb50"));
|
||
lose1.Visibility = Visibility.Hidden;
|
||
lose2.Visibility = Visibility.Hidden;
|
||
lose3.Visibility = Visibility.Hidden;
|
||
|
||
win3.Visibility = Visibility.Visible;
|
||
win4.Visibility = Visibility.Visible;
|
||
}
|
||
showElement("RankingGrid");
|
||
}
|
||
|
||
public void showElement(string name, int time = 600)
|
||
{
|
||
var Element = FindName(name) as FrameworkElement;
|
||
if (Element == null) return;
|
||
|
||
Element.Visibility = Visibility.Visible;
|
||
var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(time));
|
||
Element.BeginAnimation(UIElement.OpacityProperty, fadeIn);
|
||
}
|
||
|
||
|
||
private void DrawCirclesWithText()
|
||
{
|
||
userBox.Children.Clear();
|
||
_musicJumpRopeContext.Sports.Clear();
|
||
_musicJumpRopeContext.UserList.Clear();
|
||
_musicJumpRopeContext.UserNumberList.Clear();
|
||
_musicJumpRopeContext.UserBeatSyncList.Clear();
|
||
|
||
double imgWidth = userBox.ActualWidth;
|
||
double imgHeight = userBox.ActualHeight;
|
||
double radius = 100;
|
||
|
||
for (int i = 0; i < _musicJumpRopeContext.CirclePositions.Count; i++)
|
||
{
|
||
//var pos = _musicJumpRopeContext.CirclePositions[i == 0 ? 1 : 0];
|
||
|
||
var pos = _musicJumpRopeContext.CirclePositions[i];
|
||
|
||
double x = pos.XNorm * imgWidth;
|
||
double y = pos.YNorm * imgHeight;
|
||
|
||
// 绘制发光圆
|
||
var userItem = AddUserItem(x, y, i);
|
||
// 绑定运动对象
|
||
var sport = SportBase.Create("rope-skipping");
|
||
int indexCopy = i;
|
||
var currentItem = userItem;
|
||
|
||
// 订阅事件
|
||
sport.OnTicked += (count, times) =>
|
||
{
|
||
// 更新UI
|
||
//userItem.NumberText = count.ToString();
|
||
// 更新数字源
|
||
_musicJumpRopeContext.UserNumberList[indexCopy] = count.ToString();
|
||
|
||
if (userItem.ImageState != "2")
|
||
userItem.ImageState = "2";
|
||
//ChangeImgState(indexCopy, "2"); //改变当前图的状态
|
||
|
||
|
||
var currentTime = Utils.GetMusicCurrentTime();
|
||
int currentSecond = (int)Math.Floor(currentTime);
|
||
|
||
// 判断是否命中节拍
|
||
var beats = _musicJumpRopeContext.MusicBeats["1"];
|
||
bool hit = beats.Any(b => Math.Abs(b - currentTime) <= _beatTolerance);
|
||
if (hit)
|
||
{
|
||
_musicJumpRopeContext.UserBeatSyncList[indexCopy] += 1;
|
||
double left = _musicJumpRopeContext.UserBeatSyncList[0];
|
||
double right = _musicJumpRopeContext.UserBeatSyncList[1];
|
||
double total = left + right;
|
||
|
||
|
||
PkBar.LeftProgress = 1 - (total == 0 ? 0.5 : Math.Round(left / total, 2));
|
||
if (indexCopy == 0)
|
||
{
|
||
popSilder2.IsMiss = false;
|
||
//UpdateScore(left, score1);
|
||
score2.Text = (left * 10).ToString();
|
||
}
|
||
else
|
||
{
|
||
popSilder1.IsMiss = false;
|
||
//UpdateScore(right, score2);
|
||
score1.Text = (right * 10).ToString();
|
||
}
|
||
}
|
||
};
|
||
|
||
sport.Start();
|
||
_musicJumpRopeContext.Sports.Add(sport);
|
||
}
|
||
}
|
||
|
||
|
||
public void ShowMusicAnimation()
|
||
{
|
||
ImageBehavior.SetRepeatBehavior(leftm, RepeatBehavior.Forever);
|
||
ImageBehavior.SetRepeatBehavior(rightm, RepeatBehavior.Forever);
|
||
ImageBehavior.GetAnimationController(leftm).Play();
|
||
ImageBehavior.GetAnimationController(rightm).Play();
|
||
}
|
||
|
||
private void UpdateCircleCounts(List<Human> humans)
|
||
{
|
||
double halfW = AppSettings.AreaSize.X;
|
||
double halfH = AppSettings.AreaSize.Y;
|
||
|
||
for (int i = 0; i < _musicJumpRopeContext.CirclePositions.Count; i++)
|
||
{
|
||
var circle = _musicJumpRopeContext.CirclePositions[i];
|
||
double cx = circle.XNorm;
|
||
double cy = circle.YNorm;
|
||
|
||
Human humanInCircle = null;
|
||
|
||
// 1️⃣ 找圈内的人(单脚命中即可)
|
||
foreach (var h in humans)
|
||
{
|
||
if (sportOperate.IsAnyFootInCircle(h, cx, cy, halfW, halfH))
|
||
{
|
||
humanInCircle = h;
|
||
break; // 每个圈只认一个人
|
||
}
|
||
}
|
||
|
||
|
||
// 根据是否有人和跳绳数字判断状态
|
||
bool hasHuman = humanInCircle != null;
|
||
lock (_updateLock)
|
||
{
|
||
_musicJumpRopeContext.UserList[i].ImageState = GetJumpState(i, hasHuman);
|
||
}
|
||
|
||
// 3️⃣ 推送计数
|
||
if (hasHuman)
|
||
{
|
||
_musicJumpRopeContext.Sports[i].Pushing(humanInCircle);
|
||
}
|
||
}
|
||
}
|
||
private string GetJumpState(int circleIndex, bool humanInCircle)
|
||
{
|
||
if (!humanInCircle)
|
||
{
|
||
// 无人 → 出圈
|
||
return "3";
|
||
}
|
||
|
||
string currentNumber = _musicJumpRopeContext.UserNumberList[circleIndex];
|
||
|
||
if (!_jumpStatus.ContainsKey(circleIndex))
|
||
{
|
||
_jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "1"); // 初始状态先为停止
|
||
return "1";
|
||
}
|
||
var (lastNumber, lastChangeTime, lastState) = _jumpStatus[circleIndex];
|
||
|
||
if (currentNumber != lastNumber)
|
||
{
|
||
// 数字变化 → 跳绳中
|
||
_jumpStatus[circleIndex] = (currentNumber, DateTime.Now, "2");
|
||
return "2";
|
||
}
|
||
|
||
// 数字未变化,判断是否超过 2 秒
|
||
double elapsed = (DateTime.Now - lastChangeTime).TotalSeconds;
|
||
if (elapsed >= 0.8)
|
||
{
|
||
// 超过 2 秒未变化 → 停止
|
||
_jumpStatus[circleIndex] = (currentNumber, lastChangeTime, "1");
|
||
return "1";
|
||
}
|
||
// 维持上次状态
|
||
return lastState;
|
||
}
|
||
|
||
private MusicUserItem AddUserItem(double centerX, double centerY, int index)
|
||
{
|
||
var userItem = new MusicUserItem();
|
||
userItem.VerticalAlignment = VerticalAlignment.Top;
|
||
userItem.HorizontalAlignment = index == 1 ? HorizontalAlignment.Left : HorizontalAlignment.Right;
|
||
userItem.ImageState = "1";
|
||
userItem.Margin = index == 1 ? new Thickness(226, 345, 0, 0) : new Thickness(0, 345, 226, 0);
|
||
userBox.Children.Add(userItem);
|
||
_musicJumpRopeContext.UserList.Add(userItem);
|
||
_musicJumpRopeContext.UserNumberList.Add("0");
|
||
_musicJumpRopeContext.UserBeatSyncList.Add(0);
|
||
return userItem; //
|
||
}
|
||
|
||
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
|
||
{
|
||
popSilder1.StartMarginAnimation();
|
||
popSilder2.StartMarginAnimation();
|
||
}
|
||
}
|
||
}
|