Compare commits
3 Commits
856473f221
...
65e49f2967
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65e49f2967 | ||
|
|
26a932b447 | ||
|
|
1a32fef55c |
@ -192,9 +192,9 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
|
||||
private void UpdateLayoutWithAnimation(bool instant = false)
|
||||
{
|
||||
double centerX = ActualWidth / 2;
|
||||
double spacing = 550;
|
||||
double sideScale = 0.93;
|
||||
double centerScale = 1.43;
|
||||
double spacing = 530;
|
||||
double sideScale = 0.98;
|
||||
double centerScale = 1.33;
|
||||
|
||||
for (int i = 0; i < ItemsHost.Items.Count; i++)
|
||||
{
|
||||
@ -214,25 +214,25 @@ namespace Wpf_AiSportsMicrospace.MyUserControl
|
||||
|
||||
if (i == SelectedIndex)
|
||||
{
|
||||
targetX = centerX - 75;
|
||||
targetX = centerX - 175;
|
||||
targetScale = centerScale;
|
||||
targetOpacity = 1.0;
|
||||
}
|
||||
else if (i == SelectedIndex - 1 || (SelectedIndex == 0 && i == Images.Count - 1))
|
||||
{
|
||||
targetX = centerX - spacing - 75;
|
||||
targetX = centerX - spacing -175;
|
||||
targetScale = sideScale;
|
||||
targetOpacity = 1.0;
|
||||
}
|
||||
else if (i == SelectedIndex + 1 || (SelectedIndex == Images.Count - 1 && i == 0))
|
||||
{
|
||||
targetX = centerX + spacing - 75;
|
||||
targetX = centerX + spacing - 175;
|
||||
targetScale = sideScale;
|
||||
targetOpacity = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetX = centerX - 75;
|
||||
targetX = centerX - 175;
|
||||
targetScale = sideScale;
|
||||
targetOpacity = 0.0;
|
||||
}
|
||||
|
||||
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/play_home_bg.png
Normal file
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 14 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/play_jump.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/play_music.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/play_img/play_vs.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/test_img/test_home_bg.png
Normal file
|
After Width: | Height: | Size: 358 KiB |
|
After Width: | Height: | Size: 13 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/test_img/test_jump.png
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/test_img/test_rope.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
Wpf_AiSportsMicrospace/Resources/Img/test_img/test_situp.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
84
Wpf_AiSportsMicrospace/Views/CenterHome.xaml
Normal file
@ -0,0 +1,84 @@
|
||||
<UserControl x:Class="Wpf_AiSportsMicrospace.Views.CenterHome"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Wpf_AiSportsMicrospace.MyUserControl"
|
||||
xmlns:gif="http://wpfanimatedgif.codeplex.com"
|
||||
Height="1080" Width="1920" >
|
||||
<Grid VerticalAlignment="Bottom">
|
||||
<Grid.Background>
|
||||
<ImageBrush ImageSource="/Resources/Img/play_img/play_home_bg.png" Stretch="UniformToFill"/>
|
||||
</Grid.Background>
|
||||
|
||||
<!-- 顶部图片 -->
|
||||
<Image
|
||||
Source="/Resources/Img/play_img/play_home_title.png"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Width="615"
|
||||
Margin="0,50,0,0"
|
||||
/>
|
||||
|
||||
<!-- CoverFlowControl,距离图片80 -->
|
||||
<local:CoverFlowControl
|
||||
x:Name="coverFlow"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Height="900"
|
||||
Width="1920"
|
||||
Margin="0,180,0,0"
|
||||
Padding="0,100"
|
||||
/>
|
||||
<Grid Margin="314,833,214,0" VerticalAlignment="Top" Height="182">
|
||||
<Image
|
||||
Source="/Resources/Img/Album/change_left.png"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="330"
|
||||
Margin="0,100,0,0"
|
||||
/>
|
||||
<Image
|
||||
gif:ImageBehavior.AnimatedSource="/Resources/Img/Album/3.gif"
|
||||
gif:ImageBehavior.RepeatBehavior="Forever"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Margin="-20,10,30,20"
|
||||
/>
|
||||
|
||||
|
||||
<Image
|
||||
Source="/Resources/Img/Album/change_back.png"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Width="330"
|
||||
Margin="0,97,0,0"
|
||||
/>
|
||||
<Image
|
||||
gif:ImageBehavior.AnimatedSource="/Resources/Img/Album/2.gif"
|
||||
gif:ImageBehavior.RepeatBehavior="Forever"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Margin="513,16,0,0" Height="184" Width="146"
|
||||
/>
|
||||
|
||||
|
||||
<Image
|
||||
Source="/Resources/Img/Album/change_right.png"
|
||||
HorizontalAlignment="right"
|
||||
VerticalAlignment="Top"
|
||||
Width="330"
|
||||
Margin="0,100,0,0"
|
||||
/>
|
||||
<Image
|
||||
gif:ImageBehavior.AnimatedSource="/Resources/Img/Album/1.gif"
|
||||
gif:ImageBehavior.RepeatBehavior="Forever"
|
||||
HorizontalAlignment="right"
|
||||
VerticalAlignment="Top"
|
||||
Margin="50,10,200,20"
|
||||
/>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
253
Wpf_AiSportsMicrospace/Views/CenterHome.xaml.cs
Normal file
@ -0,0 +1,253 @@
|
||||
using Microsoft.ML.Runtime;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using Wpf_AiSportsMicrospace.Common;
|
||||
using Wpf_AiSportsMicrospace.Enum;
|
||||
using Wpf_AiSportsMicrospace.MyUserControl;
|
||||
using Wpf_AiSportsMicrospace.Views;
|
||||
using Yztob.AiSports.Inferences.Abstractions;
|
||||
using Yztob.AiSports.Postures;
|
||||
using Yztob.AiSports.Postures.Abstractions;
|
||||
using Yztob.AiSports.Postures.Sports;
|
||||
using Yztob.AiSports.Postures.Things;
|
||||
using Yztob.AiSports.Sensors.Abstractions;
|
||||
using Yztob.AiSports.Sensors.Things;
|
||||
namespace Wpf_AiSportsMicrospace.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Home.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CenterHome : UserControl
|
||||
{
|
||||
private IHumanPredictor _humanPredictor;
|
||||
private WebcamClient _webcamClient;
|
||||
private ConcurrentQueue<VideoFrame> _frameQueue = new();
|
||||
private CancellationTokenSource _cts = new();
|
||||
private SportOperate _sportOperate;
|
||||
|
||||
public String _nowSelect = "test"; //测试吧:test 游戏吧:play
|
||||
public String NowSelect
|
||||
{
|
||||
get => _nowSelect;
|
||||
set
|
||||
{
|
||||
if (_nowSelect != value)
|
||||
{
|
||||
_nowSelect = value;
|
||||
InitImg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CenterHome()
|
||||
{
|
||||
InitializeComponent();
|
||||
_humanPredictor = HumanPredictorFactory.Create(HumanPredictorType.SingleHigh);
|
||||
|
||||
//_sports = SportBase.GetSports();
|
||||
//_detectQueue = new SportDetectionQueue();
|
||||
|
||||
//string imgPath = Path.Combine(projectRoot, "Resources", "Img" , _nowSelect == "test" ? "test_img" : "play_img");
|
||||
|
||||
// 默认选中第1张
|
||||
coverFlow.SelectedIndex = 0;
|
||||
|
||||
InitImg();
|
||||
//AnimationBehavior.SetSourceUri(LoadingImage, loadingImage);
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_sportOperate = new SportOperate();
|
||||
_webcamClient = _sportOperate.CreateRTSP();
|
||||
|
||||
_webcamClient.OnExtractFrame += frame =>
|
||||
{
|
||||
if (frame != null)
|
||||
_frameQueue.Enqueue(frame);
|
||||
};
|
||||
_webcamClient.StartExtract();
|
||||
|
||||
StartFrameProcessing();
|
||||
|
||||
Utils.PlayBackgroundMusic("homeprojectselected.mp3");
|
||||
|
||||
//coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
||||
}
|
||||
private void CoverFlow_ProgressCompleted(CoverFlowItem item)
|
||||
{
|
||||
// 停止抽帧线程/释放资源
|
||||
try
|
||||
{
|
||||
_cts.Cancel(); // 停止后台处理线程
|
||||
_webcamClient?.StopExtract(); // 停止摄像头抽帧
|
||||
_webcamClient = null;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"停止抽帧异常: {ex.Message}");
|
||||
}
|
||||
|
||||
// 解绑事件,防止重复触发
|
||||
//coverFlow.ProgressCompleted -= CoverFlow_ProgressCompleted;
|
||||
|
||||
// 根据图片跳转新窗口
|
||||
string uri = item.ImageUri.ToString();
|
||||
|
||||
//if (uri.EndsWith("1.jpg"))
|
||||
// newWindow = new GroupJumpRope();
|
||||
//else if (uri.EndsWith("2.jpg"))
|
||||
// newWindow = new GroupJumpRope();
|
||||
//else if (uri.EndsWith("3.jpg"))
|
||||
// newWindow = new GroupJumpRope();
|
||||
// 找到主窗口,切换内容到 GroupJumpRopePage
|
||||
|
||||
//var mainWin = Application.Current.MainWindow as Main;
|
||||
//if (mainWin != null)
|
||||
//{
|
||||
// Utils.PlayBackgroundMusic("musicjumprope1.mp3");
|
||||
// mainWin.SwitchPage(new GroupJumpRope(), true);
|
||||
//}
|
||||
|
||||
RouterGoNew();
|
||||
}
|
||||
|
||||
private void StartFrameProcessing()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (!_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
if (_frameQueue.TryDequeue(out var frame))
|
||||
{
|
||||
ProcessFrame(frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
//_webcamClient.OnExtractFrame += frame =>
|
||||
//{
|
||||
// if (frame != null)
|
||||
// _frameQueue.Enqueue(frame);
|
||||
//};
|
||||
//_webcamClient.StartExtract();
|
||||
|
||||
_webcamClient.StartExtract();
|
||||
//Thread.Sleep(5);
|
||||
}
|
||||
}
|
||||
}, _cts.Token);
|
||||
}
|
||||
|
||||
private void ProcessFrame(VideoFrame frame)
|
||||
{
|
||||
try
|
||||
{
|
||||
var buffer = frame.GetImageBuffer(ImageFormat.Jpeg).ToArray();
|
||||
var humanResult = _humanPredictor.Predicting(buffer, frame.Number);
|
||||
|
||||
var humans = humanResult?.Humans?.ToList();
|
||||
if (humans == null || humans.Count == 0)
|
||||
return;
|
||||
|
||||
//var human = humans
|
||||
// .Where(h =>
|
||||
// h.Keypoints.Any(kp => kp.Name == "left_ankle" && kp.X < 1020 && kp.Y > 900 && kp.Y < 1020) &&
|
||||
// h.Keypoints.Any(kp => kp.Name == "right_ankle" && kp.X > 750 && kp.Y > 900 && kp.Y < 1020)
|
||||
// )
|
||||
// .FirstOrDefault();
|
||||
|
||||
var human = humans.FirstOrDefault();
|
||||
|
||||
if (human == null) return;
|
||||
|
||||
//检测挥手动作
|
||||
var wavingaction = _sportOperate.VerifyWavingAction(human);
|
||||
|
||||
// 把低 8 位作为动作类型,高 8 位作为进度
|
||||
//int actionType = wavingaction & 0xFF;
|
||||
//int progress = (wavingaction >> 8) & 0xFF;
|
||||
|
||||
switch (wavingaction)
|
||||
{
|
||||
case (int)WavingAction.LeftWave: // 左手挥动
|
||||
Dispatcher.BeginInvoke(() => coverFlow.SlideRight());
|
||||
break;
|
||||
|
||||
case (int)WavingAction.RightWave: // 右手挥动
|
||||
Dispatcher.BeginInvoke(() => coverFlow.SlideLeft());
|
||||
break;
|
||||
|
||||
case (int)WavingAction.FirstHand: // 举手开始
|
||||
Dispatcher.BeginInvoke(() => coverFlow.StartSelectedProgress());
|
||||
break;
|
||||
|
||||
case (int)WavingAction.Raising: // 举手中,实时更新进度
|
||||
break;
|
||||
|
||||
case (int)WavingAction.RaiseHand: // 举手完成
|
||||
_cts.Cancel();
|
||||
coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
||||
break;
|
||||
|
||||
default: // 没有动作 → 取消进度
|
||||
Dispatcher.BeginInvoke(() => coverFlow.CancelSelectedProgress());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("OnFrameExtracted error: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InitImg()
|
||||
{
|
||||
string projectRoot = Path.Combine(AppContext.BaseDirectory, @"..\..\..");
|
||||
coverFlow.Images.Clear(); // 先清空原有图
|
||||
if (_nowSelect == "test")
|
||||
{
|
||||
string imgPath = Path.Combine(projectRoot, "Resources", "Img", "test_img");
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "test_jump.png")), ProgressColor1 = "#215bc7", ProgressColor2 = "#fc640e" });
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "test_situp.png")), ProgressColor1 = "#e73d42", ProgressColor2 = "#fd8212" });
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "test_rope.png")), ProgressColor1 = "#e73d42", ProgressColor2 = "#215bc7" });
|
||||
}
|
||||
else
|
||||
{
|
||||
string imgPath = Path.Combine(projectRoot, "Resources", "Img", "play_img");
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "play_vs.png")), ProgressColor1 = "#215bc7", ProgressColor2 = "#fc640e" });
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "play_jump.png")), ProgressColor1 = "#e73d42", ProgressColor2 = "#fd8212" });
|
||||
coverFlow.Images.Add(new CoverFlowItem { ImageUri = new Uri(Path.Combine(imgPath, "play_music.png")), ProgressColor1 = "#e73d42", ProgressColor2 = "#215bc7" });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//跳转二级页面
|
||||
private void RouterGoNew()
|
||||
{
|
||||
// 跳转逻辑(如导航到新页面并传递参数)
|
||||
// 例如:RaiseEvent、调用外部委托、或使用导航框架
|
||||
var mainWin = Application.Current.MainWindow as Main;
|
||||
var newPage = new GroupJumpRope();
|
||||
mainWin?.SwitchPage(newPage, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Width="615"
|
||||
Margin="0,100,0,0"
|
||||
Margin="0,50,0,0"
|
||||
/>
|
||||
|
||||
<!-- CoverFlowControl,距离图片80 -->
|
||||
@ -25,12 +25,13 @@
|
||||
VerticalAlignment="Top"
|
||||
Height="900"
|
||||
Width="1920"
|
||||
Margin="0,250,0,0"
|
||||
Margin="0,180,0,0"
|
||||
Padding="0,100"
|
||||
/>
|
||||
<Grid Margin="314,803,314,0" VerticalAlignment="Top" Height="182">
|
||||
<Grid Margin="314,833,214,0" VerticalAlignment="Top" Height="182">
|
||||
<Image
|
||||
Source="/Resources/Img/Album/change_back.png"
|
||||
MouseDown="GoNew"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Width="330"
|
||||
@ -60,12 +61,6 @@
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Image
|
||||
gif:ImageBehavior.AnimatedSource="/Resources/Img/Album/3.gif"
|
||||
gif:ImageBehavior.RepeatBehavior="Forever"
|
||||
HorizontalAlignment="right"
|
||||
VerticalAlignment="Top"
|
||||
Margin="100,120,200,20"
|
||||
/>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@ -11,8 +11,10 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using Wpf_AiSportsMicrospace;
|
||||
using Wpf_AiSportsMicrospace.Common;
|
||||
using Wpf_AiSportsMicrospace.Enum;
|
||||
using Wpf_AiSportsMicrospace.MyUserControl;
|
||||
@ -38,7 +40,6 @@ namespace Wpf_AiSportsMicrospace
|
||||
private SportOperate _sportOperate;
|
||||
public static Uri loadingImage = new Uri("/Resources/Img/Album/1.gif", UriKind.Relative);
|
||||
|
||||
|
||||
public Home()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -70,19 +71,19 @@ namespace Wpf_AiSportsMicrospace
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//_sportOperate = new SportOperate();
|
||||
//_webcamClient = _sportOperate.CreateRTSP();
|
||||
_sportOperate = new SportOperate();
|
||||
_webcamClient = _sportOperate.CreateRTSP();
|
||||
|
||||
//_webcamClient.OnExtractFrame += frame =>
|
||||
//{
|
||||
// if (frame != null)
|
||||
// _frameQueue.Enqueue(frame);
|
||||
//};
|
||||
//_webcamClient.StartExtract();
|
||||
_webcamClient.OnExtractFrame += frame =>
|
||||
{
|
||||
if (frame != null)
|
||||
_frameQueue.Enqueue(frame);
|
||||
};
|
||||
_webcamClient.StartExtract();
|
||||
|
||||
StartFrameProcessing();
|
||||
|
||||
Utils.PlayBackgroundMusic("homeprojectselected.mp3");
|
||||
//Utils.PlayBackgroundMusic("homeprojectselected.mp3");
|
||||
|
||||
//coverFlow.ProgressCompleted += CoverFlow_ProgressCompleted;
|
||||
}
|
||||
@ -105,7 +106,7 @@ namespace Wpf_AiSportsMicrospace
|
||||
//coverFlow.ProgressCompleted -= CoverFlow_ProgressCompleted;
|
||||
|
||||
// 根据图片跳转新窗口
|
||||
string uri = item.ImageUri.ToString();
|
||||
//string uri = item.ImageUri.ToString();
|
||||
|
||||
//if (uri.EndsWith("1.jpg"))
|
||||
// newWindow = new GroupJumpRope();
|
||||
@ -115,12 +116,13 @@ namespace Wpf_AiSportsMicrospace
|
||||
// newWindow = new GroupJumpRope();
|
||||
// 找到主窗口,切换内容到 GroupJumpRopePage
|
||||
|
||||
var mainWin = Application.Current.MainWindow as Main;
|
||||
if (mainWin != null)
|
||||
{
|
||||
Utils.PlayBackgroundMusic("musicjumprope1.mp3");
|
||||
mainWin.SwitchPage(new GroupJumpRope(), true);
|
||||
}
|
||||
//var mainWin = Application.Current.MainWindow as Main;
|
||||
//if (mainWin != null)
|
||||
//{
|
||||
// Utils.PlayBackgroundMusic("musicjumprope1.mp3");
|
||||
// mainWin.SwitchPage(new GroupJumpRope(), true);
|
||||
//}
|
||||
RouterGoNew();
|
||||
}
|
||||
private void StartFrameProcessing()
|
||||
{
|
||||
@ -207,5 +209,31 @@ namespace Wpf_AiSportsMicrospace
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
//测试点击
|
||||
private void GoNew(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// 跳转逻辑(如导航到新页面并传递参数)
|
||||
// 例如:RaiseEvent、调用外部委托、或使用导航框架
|
||||
var mainWin = Application.Current.MainWindow as Main;
|
||||
var newPage = new CenterHome
|
||||
{
|
||||
NowSelect = coverFlow.SelectedIndex == 0 ? "test" : "play"
|
||||
};
|
||||
mainWin?.SwitchPage(newPage, true);
|
||||
}
|
||||
|
||||
//跳转二级页面
|
||||
private void RouterGoNew()
|
||||
{
|
||||
// 跳转逻辑(如导航到新页面并传递参数)
|
||||
// 例如:RaiseEvent、调用外部委托、或使用导航框架
|
||||
var mainWin = Application.Current.MainWindow as Main;
|
||||
var newPage = new CenterHome
|
||||
{
|
||||
NowSelect = coverFlow.SelectedIndex == 0 ? "test" : "play"
|
||||
};
|
||||
mainWin?.SwitchPage(newPage, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,15 +27,79 @@ namespace Wpf_AiSportsMicrospace.Views
|
||||
// 默认显示首页
|
||||
MainContent.Content = new Home();
|
||||
}
|
||||
//public void SwitchPage(UserControl newPage, bool fromRight)
|
||||
//{
|
||||
// if (MainContent.Content == newPage) return;
|
||||
|
||||
// var oldPage = MainContent.Content as UserControl;
|
||||
|
||||
// if (oldPage != null)
|
||||
// {
|
||||
// // 旧页面动画
|
||||
// var oldTransformGroup = new TransformGroup();
|
||||
// var oldScale = new ScaleTransform(1, 1);
|
||||
// var oldSkew = new SkewTransform(0, 0);
|
||||
// var oldTranslate = new TranslateTransform(0, 0);
|
||||
// oldTransformGroup.Children.Add(oldScale);
|
||||
// oldTransformGroup.Children.Add(oldSkew);
|
||||
// oldTransformGroup.Children.Add(oldTranslate);
|
||||
// oldPage.RenderTransformOrigin = new Point(fromRight ? 1 : 0, 0.5); // 左右翻页中心
|
||||
// oldPage.RenderTransform = oldTransformGroup;
|
||||
|
||||
// var scaleAnim = new DoubleAnimation(1, 0.7, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
// var skewAnim = new DoubleAnimation(0, fromRight ? 45 : -45, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
// var fadeAnim = new DoubleAnimation(1, 0.2, TimeSpan.FromMilliseconds(600));
|
||||
// var translateAnim = new DoubleAnimation(0, fromRight ? -ActualWidth : ActualWidth, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
|
||||
// oldScale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnim);
|
||||
// oldScale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnim);
|
||||
// oldSkew.BeginAnimation(SkewTransform.AngleYProperty, skewAnim);
|
||||
// oldTranslate.BeginAnimation(TranslateTransform.XProperty, translateAnim);
|
||||
// oldPage.BeginAnimation(OpacityProperty, fadeAnim);
|
||||
|
||||
// fadeAnim.Completed += (s, e) =>
|
||||
// {
|
||||
// MainContent.Content = newPage;
|
||||
// AnimateNewPageEnhanced(newPage, fromRight);
|
||||
// };
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// MainContent.Content = newPage;
|
||||
// AnimateNewPageEnhanced(newPage, fromRight);
|
||||
// }
|
||||
//}
|
||||
|
||||
public void SwitchPage(UserControl newPage, bool fromRight)
|
||||
{
|
||||
if (MainContent.Content == newPage) return;
|
||||
|
||||
var oldPage = MainContent.Content as UserControl;
|
||||
|
||||
// 预加载新页面资源
|
||||
PreloadPageResources(newPage);
|
||||
|
||||
if (oldPage != null)
|
||||
{
|
||||
// 旧页面动画
|
||||
MainContent.Content = null;
|
||||
// 创建容器同时显示新旧页面
|
||||
var container = new Grid();
|
||||
container.Children.Add(newPage); // 新页面在底层
|
||||
container.Children.Add(oldPage); // 旧页面在顶层
|
||||
|
||||
MainContent.Content = container;
|
||||
|
||||
// 设置新页面初始状态 - 轻微缩放和偏移
|
||||
var newTransformGroup = new TransformGroup();
|
||||
var newScale = new ScaleTransform(0.95, 0.95);
|
||||
var newTranslate = new TranslateTransform(fromRight ? 80 : -80, 0);
|
||||
newTransformGroup.Children.Add(newScale);
|
||||
newTransformGroup.Children.Add(newTranslate);
|
||||
newPage.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
newPage.RenderTransform = newTransformGroup;
|
||||
newPage.Opacity = 1;
|
||||
|
||||
// 旧页面动画 - 飞出效果
|
||||
var oldTransformGroup = new TransformGroup();
|
||||
var oldScale = new ScaleTransform(1, 1);
|
||||
var oldSkew = new SkewTransform(0, 0);
|
||||
@ -43,33 +107,74 @@ namespace Wpf_AiSportsMicrospace.Views
|
||||
oldTransformGroup.Children.Add(oldScale);
|
||||
oldTransformGroup.Children.Add(oldSkew);
|
||||
oldTransformGroup.Children.Add(oldTranslate);
|
||||
oldPage.RenderTransformOrigin = new Point(fromRight ? 1 : 0, 0.5); // 左右翻页中心
|
||||
oldPage.RenderTransformOrigin = new Point(fromRight ? 1 : 0, 0.5);
|
||||
oldPage.RenderTransform = oldTransformGroup;
|
||||
oldPage.Opacity = 1;
|
||||
|
||||
var scaleAnim = new DoubleAnimation(1, 0.7, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
var skewAnim = new DoubleAnimation(0, fromRight ? 45 : -45, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
var fadeAnim = new DoubleAnimation(1, 0.2, TimeSpan.FromMilliseconds(600));
|
||||
var translateAnim = new DoubleAnimation(0, fromRight ? -ActualWidth : ActualWidth, TimeSpan.FromMilliseconds(600)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
|
||||
// 动画参数
|
||||
var duration = TimeSpan.FromMilliseconds(1200);
|
||||
var easing = new CubicEase { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
oldScale.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnim);
|
||||
oldScale.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnim);
|
||||
oldSkew.BeginAnimation(SkewTransform.AngleYProperty, skewAnim);
|
||||
oldTranslate.BeginAnimation(TranslateTransform.XProperty, translateAnim);
|
||||
oldPage.BeginAnimation(OpacityProperty, fadeAnim);
|
||||
|
||||
fadeAnim.Completed += (s, e) =>
|
||||
// 旧页面飞出动画
|
||||
var oldScaleAnim = new DoubleAnimation(1, 1.1, duration) { EasingFunction = easing };
|
||||
var oldSkewAnim = new DoubleAnimation(0, fromRight ? 15 : -15, duration) { EasingFunction = easing };
|
||||
var oldTranslateAnim = new DoubleAnimation(0, fromRight ? ActualWidth * 1.1 : -ActualWidth * 1.1, duration)
|
||||
{
|
||||
EasingFunction = easing
|
||||
};
|
||||
|
||||
// 新页面进入动画
|
||||
var newScaleAnim = new DoubleAnimation(0.8, 1, duration) { EasingFunction = easing };
|
||||
var newTranslateAnim = new DoubleAnimation(fromRight ? -80 : -80, 0, duration) { EasingFunction = easing };
|
||||
|
||||
// 开始动画
|
||||
oldScale.BeginAnimation(ScaleTransform.ScaleXProperty, oldScaleAnim);
|
||||
oldScale.BeginAnimation(ScaleTransform.ScaleYProperty, oldScaleAnim);
|
||||
oldSkew.BeginAnimation(SkewTransform.AngleYProperty, oldSkewAnim);
|
||||
oldTranslate.BeginAnimation(TranslateTransform.XProperty, oldTranslateAnim);
|
||||
|
||||
newScale.BeginAnimation(ScaleTransform.ScaleXProperty, newScaleAnim);
|
||||
newScale.BeginAnimation(ScaleTransform.ScaleYProperty, newScaleAnim);
|
||||
newTranslate.BeginAnimation(TranslateTransform.XProperty, newTranslateAnim);
|
||||
|
||||
// 动画完成后清理
|
||||
oldTranslateAnim.Completed += (s, e) =>
|
||||
{
|
||||
// 确保最终状态
|
||||
newPage.RenderTransform = null;
|
||||
newPage.Opacity = 1;
|
||||
|
||||
// 切换到只有新页面
|
||||
MainContent.Content = newPage;
|
||||
AnimateNewPageEnhanced(newPage, fromRight);
|
||||
|
||||
// 清理资源
|
||||
if (oldPage is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
|
||||
container.Children.Clear();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
MainContent.Content = newPage;
|
||||
AnimateNewPageEnhanced(newPage, fromRight);
|
||||
newPage.Opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void PreloadPageResources(UserControl page)
|
||||
{
|
||||
// 先从原来的父容器中移除页面(如果存在)
|
||||
if (page.Parent != null)
|
||||
{
|
||||
var parent = page.Parent as Panel;
|
||||
parent?.Children.Remove(page);
|
||||
}
|
||||
|
||||
// 强制WPF加载所有资源
|
||||
page.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
page.Arrange(new Rect(0, 0, page.DesiredSize.Width, page.DesiredSize.Height));
|
||||
}
|
||||
|
||||
private void AnimateNewPageEnhanced(UserControl newPage, bool fromRight)
|
||||
{
|
||||
var transformGroup = new TransformGroup();
|
||||
|
||||
@ -38,6 +38,16 @@
|
||||
<None Remove="Resources\Img\gif\1.gif" />
|
||||
<None Remove="Resources\Img\gif\2.gif" />
|
||||
<None Remove="Resources\Img\gif\3.gif" />
|
||||
<None Remove="Resources\Img\play_img\play_home_bg.png" />
|
||||
<None Remove="Resources\Img\play_img\play_home_title.png" />
|
||||
<None Remove="Resources\Img\play_img\play_jump.png" />
|
||||
<None Remove="Resources\Img\play_img\play_music.png" />
|
||||
<None Remove="Resources\Img\play_img\play_vs.png" />
|
||||
<None Remove="Resources\Img\test_img\test_home_bg.png" />
|
||||
<None Remove="Resources\Img\test_img\test_home_title.png" />
|
||||
<None Remove="Resources\Img\test_img\test_jump.png" />
|
||||
<None Remove="Resources\Img\test_img\test_rope.png" />
|
||||
<None Remove="Resources\Img\test_img\test_situp.png" />
|
||||
<None Remove="Resources\Music\homeprojectselected.mp3" />
|
||||
<None Remove="Resources\Music\homeprojectselected1.mp3" />
|
||||
<None Remove="Resources\Music\musicjumprope.mp3" />
|
||||
@ -170,6 +180,36 @@
|
||||
<Resource Include="Resources\Img\gif\3.gif">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\play_home_bg.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\play_home_title.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\play_jump.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\play_music.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\play_img\play_vs.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\test_img\test_home_bg.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\test_img\test_home_title.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\test_img\test_jump.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\test_img\test_rope.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Img\test_img\test_situp.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
<Resource Include="Resources\Music\homeprojectselected.mp3">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
|
||||