mirror of
https://github.com/LanZhan-Harmony/WindowsMusicPlayer-TheUntamedMusicPlayer.git
synced 2026-05-06 19:20:18 +08:00
修复动画错误逻辑
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Numerics;
|
||||||
using Microsoft.UI.Dispatching;
|
using Microsoft.UI.Dispatching;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Hosting;
|
||||||
using Microsoft.UI.Xaml.Input;
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
using Microsoft.UI.Xaml.Media.Imaging;
|
||||||
using UntamedMusicPlayer.Controls;
|
using UntamedMusicPlayer.Controls;
|
||||||
using UntamedMusicPlayer.Models;
|
using UntamedMusicPlayer.Models;
|
||||||
using UntamedMusicPlayer.Playback;
|
using UntamedMusicPlayer.Playback;
|
||||||
@@ -15,6 +18,8 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
{
|
{
|
||||||
public LyricViewModel ViewModel { get; }
|
public LyricViewModel ViewModel { get; }
|
||||||
|
|
||||||
|
private bool isFirstLoad = true;
|
||||||
|
|
||||||
private readonly Timer _autoScrollDelayTimer;
|
private readonly Timer _autoScrollDelayTimer;
|
||||||
private bool _isManualScrolling;
|
private bool _isManualScrolling;
|
||||||
private bool _isProgrammaticScroll;
|
private bool _isProgrammaticScroll;
|
||||||
@@ -27,13 +32,7 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
private DateTimeOffset _contentGridMarginAnimationStart;
|
private DateTimeOffset _contentGridMarginAnimationStart;
|
||||||
private double _contentGridMarginFrom;
|
private double _contentGridMarginFrom;
|
||||||
private double _contentGridMarginTo;
|
private double _contentGridMarginTo;
|
||||||
|
private CancellationTokenSource? _coverLoadWaitCts;
|
||||||
private DispatcherQueueTimer? _coverSizeAnimationTimer;
|
|
||||||
private DateTimeOffset _coverSizeAnimationStart;
|
|
||||||
private double _coverSizeFromWidth;
|
|
||||||
private double _coverSizeFromHeight;
|
|
||||||
private double _coverSizeToWidth;
|
|
||||||
private double _coverSizeToHeight;
|
|
||||||
|
|
||||||
public LyricPage()
|
public LyricPage()
|
||||||
{
|
{
|
||||||
@@ -57,13 +56,89 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
{
|
{
|
||||||
if (ReferenceGrid.ActualWidth > 0 && ReferenceGrid.ActualHeight > 0)
|
if (ReferenceGrid.ActualWidth > 0 && ReferenceGrid.ActualHeight > 0)
|
||||||
{
|
{
|
||||||
ChangeCoverSize(ReferenceGrid.ActualWidth, ReferenceGrid.ActualHeight);
|
RestartWaitForCoverAndRecalculate();
|
||||||
}
|
}
|
||||||
_isManualScrolling = false;
|
_isManualScrolling = false;
|
||||||
_autoScrollDelayTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
_autoScrollDelayTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RestartWaitForCoverAndRecalculate()
|
||||||
|
{
|
||||||
|
_coverLoadWaitCts?.Cancel();
|
||||||
|
_coverLoadWaitCts?.Dispose();
|
||||||
|
_coverLoadWaitCts = new CancellationTokenSource();
|
||||||
|
_ = RecalculateCoverSizeWhenCoverReadyAsync(_coverLoadWaitCts.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RecalculateCoverSizeWhenCoverReadyAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var cover = Data.PlayState.CurrentSong?.Cover;
|
||||||
|
if (cover is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loaded = await WaitCoverLoadedAsync(cover, cancellationToken);
|
||||||
|
if (!loaded || cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceGrid.ActualWidth > 0 && ReferenceGrid.ActualHeight > 0)
|
||||||
|
{
|
||||||
|
ChangeCoverSize(ReferenceGrid.ActualWidth, ReferenceGrid.ActualHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> WaitCoverLoadedAsync(
|
||||||
|
BitmapImage cover,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (cover.PixelWidth > 0 && cover.PixelHeight > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tcs = new TaskCompletionSource<bool>(
|
||||||
|
TaskCreationOptions.RunContinuationsAsynchronously
|
||||||
|
);
|
||||||
|
|
||||||
|
void OnImageOpened(object sender, RoutedEventArgs args) => tcs.TrySetResult(true);
|
||||||
|
void OnImageFailed(object sender, ExceptionRoutedEventArgs args) => tcs.TrySetResult(false);
|
||||||
|
|
||||||
|
cover.ImageOpened += OnImageOpened;
|
||||||
|
cover.ImageFailed += OnImageFailed;
|
||||||
|
|
||||||
|
using var cancellationRegistration = cancellationToken.Register(() =>
|
||||||
|
tcs.TrySetCanceled(cancellationToken)
|
||||||
|
);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cover.PixelWidth > 0 && cover.PixelHeight > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var completedTask = await Task.WhenAny(tcs.Task, Task.Delay(1500, cancellationToken));
|
||||||
|
if (completedTask != tcs.Task)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return await tcs.Task;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
cover.ImageOpened -= OnImageOpened;
|
||||||
|
cover.ImageFailed -= OnImageFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRootPlayBarChanged(object? sender, PropertyChangedEventArgs e)
|
private void OnRootPlayBarChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@@ -308,6 +383,14 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFirstLoad)
|
||||||
|
{
|
||||||
|
isFirstLoad = false;
|
||||||
|
CoverBorder.Width = targetWidth;
|
||||||
|
CoverBorder.Height = targetHeight;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Math.Abs(currentWidth - targetWidth) < 0.5
|
Math.Abs(currentWidth - targetWidth) < 0.5
|
||||||
&& Math.Abs(currentHeight - targetHeight) < 0.5
|
&& Math.Abs(currentHeight - targetHeight) < 0.5
|
||||||
@@ -318,40 +401,23 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_coverSizeAnimationTimer ??= DispatcherQueue.CreateTimer();
|
CoverBorder.Width = targetWidth;
|
||||||
_coverSizeAnimationTimer.Stop();
|
CoverBorder.Height = targetHeight;
|
||||||
_coverSizeAnimationTimer.Interval = TimeSpan.FromMilliseconds(16);
|
|
||||||
_coverSizeAnimationTimer.Tick -= CoverSizeAnimationTick;
|
|
||||||
_coverSizeAnimationTimer.Tick += CoverSizeAnimationTick;
|
|
||||||
|
|
||||||
_coverSizeFromWidth = currentWidth;
|
var visual = ElementCompositionPreview.GetElementVisual(CoverBorder);
|
||||||
_coverSizeFromHeight = currentHeight;
|
visual.StopAnimation("Scale");
|
||||||
_coverSizeToWidth = targetWidth;
|
visual.CenterPoint = new Vector3((float)(targetWidth / 2), (float)(targetHeight / 2), 0f);
|
||||||
_coverSizeToHeight = targetHeight;
|
|
||||||
_coverSizeAnimationStart = DateTimeOffset.Now;
|
|
||||||
|
|
||||||
_coverSizeAnimationTimer.Start();
|
var initialScaleX = (float)(currentWidth / targetWidth);
|
||||||
}
|
var initialScaleY = (float)(currentHeight / targetHeight);
|
||||||
|
visual.Scale = new Vector3(initialScaleX, initialScaleY, 1f);
|
||||||
|
|
||||||
private void CoverSizeAnimationTick(DispatcherQueueTimer sender, object args)
|
var compositor = visual.Compositor;
|
||||||
{
|
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
|
||||||
const double durationMs = 450;
|
scaleAnimation.InsertKeyFrame(1f, Vector3.One);
|
||||||
var elapsedMs = (DateTimeOffset.Now - _coverSizeAnimationStart).TotalMilliseconds;
|
scaleAnimation.Duration = TimeSpan.FromMilliseconds(450);
|
||||||
var progress = Math.Clamp(elapsedMs / durationMs, 0d, 1d);
|
|
||||||
var easedProgress = 1 - Math.Pow(1 - progress, 3);
|
|
||||||
|
|
||||||
CoverBorder.Width =
|
visual.StartAnimation("Scale", scaleAnimation);
|
||||||
_coverSizeFromWidth + ((_coverSizeToWidth - _coverSizeFromWidth) * easedProgress);
|
|
||||||
CoverBorder.Height =
|
|
||||||
_coverSizeFromHeight + ((_coverSizeToHeight - _coverSizeFromHeight) * easedProgress);
|
|
||||||
|
|
||||||
if (progress >= 1)
|
|
||||||
{
|
|
||||||
sender.Stop();
|
|
||||||
sender.Tick -= CoverSizeAnimationTick;
|
|
||||||
CoverBorder.Width = _coverSizeToWidth;
|
|
||||||
CoverBorder.Height = _coverSizeToHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
|
private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
@@ -431,12 +497,12 @@ public sealed partial class LyricPage : Page, IDisposable
|
|||||||
{
|
{
|
||||||
_autoScrollDelayTimer.Dispose();
|
_autoScrollDelayTimer.Dispose();
|
||||||
_titleBarHideTimer?.Dispose();
|
_titleBarHideTimer?.Dispose();
|
||||||
|
_coverLoadWaitCts?.Cancel();
|
||||||
|
_coverLoadWaitCts?.Dispose();
|
||||||
|
_coverLoadWaitCts = null;
|
||||||
_contentGridMarginAnimationTimer?.Stop();
|
_contentGridMarginAnimationTimer?.Stop();
|
||||||
_contentGridMarginAnimationTimer?.Tick -= ContentGridMarginAnimationTick;
|
_contentGridMarginAnimationTimer?.Tick -= ContentGridMarginAnimationTick;
|
||||||
_contentGridMarginAnimationTimer = null;
|
_contentGridMarginAnimationTimer = null;
|
||||||
_coverSizeAnimationTimer?.Stop();
|
|
||||||
_coverSizeAnimationTimer?.Tick -= CoverSizeAnimationTick;
|
|
||||||
_coverSizeAnimationTimer = null;
|
|
||||||
Data.PlayState.PropertyChanged -= OnStateChanged;
|
Data.PlayState.PropertyChanged -= OnStateChanged;
|
||||||
Data.RootPlayBarViewModel?.PropertyChanged -= OnRootPlayBarChanged;
|
Data.RootPlayBarViewModel?.PropertyChanged -= OnRootPlayBarChanged;
|
||||||
Data.LyricPage = null;
|
Data.LyricPage = null;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:model="using:UntamedMusicPlayer.Models"
|
xmlns:model="using:UntamedMusicPlayer.Models"
|
||||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||||
Unloaded="RootPlayBarView_Unloaded"
|
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<Grid KeyTipPlacementMode="Top">
|
<Grid KeyTipPlacementMode="Top">
|
||||||
@@ -215,41 +214,22 @@
|
|||||||
</Border>
|
</Border>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Width="6" Visibility="{x:Bind GetNotDetailedVisibility(ViewModel.IsDetail), Mode=OneWay}"/>
|
<TextBlock Width="6" Visibility="{x:Bind GetNotDetailedVisibility(ViewModel.IsDetail), Mode=OneWay}"/>
|
||||||
<Grid x:Name="SongInfoTransitionHost"
|
<StackPanel Margin="0,0,4,0" HorizontalAlignment="Left"
|
||||||
Margin="0,0,4,0" HorizontalAlignment="Left"
|
VerticalAlignment="Center">
|
||||||
VerticalAlignment="Center">
|
<TextBlock x:Name="SongTitleTextBlock"
|
||||||
<StackPanel x:Name="CurrentSongInfoPanel">
|
Margin="10,0,0,4"
|
||||||
<StackPanel.RenderTransform>
|
FontSize="20" FontWeight="Medium"
|
||||||
<CompositeTransform x:Name="CurrentSongInfoTransform"/>
|
Text="{x:Bind model:Data.PlayState.CurrentSong.Title, Mode=OneWay}"
|
||||||
</StackPanel.RenderTransform>
|
TextTrimming="CharacterEllipsis"
|
||||||
<TextBlock x:Name="SongTitleTextBlock"
|
TextWrapping="NoWrap"/>
|
||||||
Margin="10,0,0,4"
|
<TextBlock x:Name="ArtistAndAlbumTextBlock"
|
||||||
FontSize="20" FontWeight="Medium"
|
Margin="10,0,0,0"
|
||||||
TextTrimming="CharacterEllipsis"
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
TextWrapping="NoWrap"/>
|
Text="{x:Bind model:Data.PlayState.CurrentSong.ArtistAndAlbumStr, Mode=OneWay}"
|
||||||
<TextBlock x:Name="ArtistAndAlbumTextBlock"
|
TextTrimming="CharacterEllipsis"
|
||||||
Margin="10,0,0,0"
|
TextWrapping="NoWrap"
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
Visibility="{x:Bind GetArtistAndAlbumStrVisibility(model:Data.PlayState.CurrentSong), Mode=OneWay}"/>
|
||||||
TextTrimming="CharacterEllipsis"
|
</StackPanel>
|
||||||
TextWrapping="NoWrap"/>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel x:Name="IncomingSongInfoPanel"
|
|
||||||
Opacity="0" Visibility="Collapsed">
|
|
||||||
<StackPanel.RenderTransform>
|
|
||||||
<CompositeTransform x:Name="IncomingSongInfoTransform" TranslateY="16"/>
|
|
||||||
</StackPanel.RenderTransform>
|
|
||||||
<TextBlock x:Name="IncomingSongTitleTextBlock"
|
|
||||||
Margin="10,0,0,4"
|
|
||||||
FontSize="20" FontWeight="Medium"
|
|
||||||
TextTrimming="CharacterEllipsis"
|
|
||||||
TextWrapping="NoWrap"/>
|
|
||||||
<TextBlock x:Name="IncomingArtistAndAlbumTextBlock"
|
|
||||||
Margin="10,0,0,0"
|
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
||||||
TextTrimming="CharacterEllipsis"
|
|
||||||
TextWrapping="NoWrap"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
<TextBlock Width="8" Visibility="{x:Bind ViewModel.IsDetail, Mode=OneWay}"/>
|
<TextBlock Width="8" Visibility="{x:Bind ViewModel.IsDetail, Mode=OneWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Input;
|
using Microsoft.UI.Xaml.Input;
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Media.Animation;
|
|
||||||
using UntamedMusicPlayer.Contracts.Models;
|
using UntamedMusicPlayer.Contracts.Models;
|
||||||
using UntamedMusicPlayer.Controls;
|
using UntamedMusicPlayer.Controls;
|
||||||
using UntamedMusicPlayer.Helpers;
|
using UntamedMusicPlayer.Helpers;
|
||||||
@@ -18,7 +15,6 @@ namespace UntamedMusicPlayer.Views;
|
|||||||
public sealed partial class RootPlayBarView : UserControl
|
public sealed partial class RootPlayBarView : UserControl
|
||||||
{
|
{
|
||||||
private bool _hasPointerPressed = false;
|
private bool _hasPointerPressed = false;
|
||||||
private Storyboard? _songInfoTransitionStoryboard;
|
|
||||||
|
|
||||||
public RootPlayBarViewModel ViewModel { get; }
|
public RootPlayBarViewModel ViewModel { get; }
|
||||||
|
|
||||||
@@ -28,119 +24,6 @@ public sealed partial class RootPlayBarView : UserControl
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ViewModel = App.GetService<RootPlayBarViewModel>();
|
ViewModel = App.GetService<RootPlayBarViewModel>();
|
||||||
Data.RootPlayBarView = this;
|
Data.RootPlayBarView = this;
|
||||||
|
|
||||||
Data.PlayState.PropertyChanged += OnStateChanged;
|
|
||||||
UpdateSongInfoWithoutAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnStateChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.PropertyName is nameof(SharedPlaybackState.CurrentSong))
|
|
||||||
{
|
|
||||||
AnimateSongInfoToCurrentSong();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateSongInfoWithoutAnimation()
|
|
||||||
{
|
|
||||||
var title = Data.PlayState.CurrentSong?.Title ?? "";
|
|
||||||
var artistAndAlbum = Data.PlayState.CurrentSong?.ArtistAndAlbumStr ?? "";
|
|
||||||
|
|
||||||
SongTitleTextBlock.Text = title;
|
|
||||||
ArtistAndAlbumTextBlock.Text = artistAndAlbum;
|
|
||||||
ArtistAndAlbumTextBlock.Visibility = string.IsNullOrWhiteSpace(artistAndAlbum)
|
|
||||||
? Visibility.Collapsed
|
|
||||||
: Visibility.Visible;
|
|
||||||
|
|
||||||
CurrentSongInfoPanel.Opacity = 1;
|
|
||||||
IncomingSongInfoPanel.Visibility = Visibility.Collapsed;
|
|
||||||
IncomingSongInfoPanel.Opacity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AnimateSongInfoToCurrentSong()
|
|
||||||
{
|
|
||||||
var title = Data.PlayState.CurrentSong?.Title ?? "";
|
|
||||||
var artistAndAlbum = Data.PlayState.CurrentSong?.ArtistAndAlbumStr ?? "";
|
|
||||||
if (SongTitleTextBlock.Text == title && ArtistAndAlbumTextBlock.Text == artistAndAlbum)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
StopSongInfoTransition();
|
|
||||||
|
|
||||||
IncomingSongTitleTextBlock.Text = title;
|
|
||||||
IncomingArtistAndAlbumTextBlock.Text = artistAndAlbum;
|
|
||||||
IncomingArtistAndAlbumTextBlock.Visibility = string.IsNullOrWhiteSpace(artistAndAlbum)
|
|
||||||
? Visibility.Collapsed
|
|
||||||
: Visibility.Visible;
|
|
||||||
|
|
||||||
IncomingSongInfoPanel.Visibility = Visibility.Visible;
|
|
||||||
|
|
||||||
var currentFadeOut = new DoubleAnimation
|
|
||||||
{
|
|
||||||
From = 1,
|
|
||||||
To = 0,
|
|
||||||
Duration = TimeSpan.FromMilliseconds(200),
|
|
||||||
};
|
|
||||||
Storyboard.SetTarget(currentFadeOut, CurrentSongInfoPanel);
|
|
||||||
Storyboard.SetTargetProperty(currentFadeOut, nameof(Opacity));
|
|
||||||
|
|
||||||
var currentSlideUp = new DoubleAnimation
|
|
||||||
{
|
|
||||||
From = 0,
|
|
||||||
To = -70,
|
|
||||||
Duration = TimeSpan.FromMilliseconds(220),
|
|
||||||
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn },
|
|
||||||
};
|
|
||||||
Storyboard.SetTarget(currentSlideUp, CurrentSongInfoTransform);
|
|
||||||
Storyboard.SetTargetProperty(currentSlideUp, nameof(CompositeTransform.TranslateY));
|
|
||||||
|
|
||||||
var incomingFadeIn = new DoubleAnimation
|
|
||||||
{
|
|
||||||
From = 0,
|
|
||||||
To = 1,
|
|
||||||
Duration = TimeSpan.FromMilliseconds(400),
|
|
||||||
};
|
|
||||||
Storyboard.SetTarget(incomingFadeIn, IncomingSongInfoPanel);
|
|
||||||
Storyboard.SetTargetProperty(incomingFadeIn, nameof(Opacity));
|
|
||||||
|
|
||||||
var incomingSlideIn = new DoubleAnimation
|
|
||||||
{
|
|
||||||
From = 70,
|
|
||||||
To = 0,
|
|
||||||
Duration = TimeSpan.FromMilliseconds(450),
|
|
||||||
EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut },
|
|
||||||
};
|
|
||||||
Storyboard.SetTarget(incomingSlideIn, IncomingSongInfoTransform);
|
|
||||||
Storyboard.SetTargetProperty(incomingSlideIn, nameof(CompositeTransform.TranslateY));
|
|
||||||
|
|
||||||
_songInfoTransitionStoryboard = new Storyboard();
|
|
||||||
_songInfoTransitionStoryboard.Children.Add(currentFadeOut);
|
|
||||||
_songInfoTransitionStoryboard.Children.Add(currentSlideUp);
|
|
||||||
_songInfoTransitionStoryboard.Children.Add(incomingFadeIn);
|
|
||||||
_songInfoTransitionStoryboard.Children.Add(incomingSlideIn);
|
|
||||||
_songInfoTransitionStoryboard.Completed += SongInfoTransitionStoryboard_Completed;
|
|
||||||
_songInfoTransitionStoryboard.Begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SongInfoTransitionStoryboard_Completed(object? sender, object e)
|
|
||||||
{
|
|
||||||
ArtistAndAlbumTextBlock.Visibility = IncomingArtistAndAlbumTextBlock.Visibility;
|
|
||||||
IncomingSongInfoPanel.Visibility = Visibility.Collapsed;
|
|
||||||
StopSongInfoTransition();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopSongInfoTransition()
|
|
||||||
{
|
|
||||||
SongTitleTextBlock.Text = IncomingSongTitleTextBlock.Text;
|
|
||||||
ArtistAndAlbumTextBlock.Text = IncomingArtistAndAlbumTextBlock.Text;
|
|
||||||
if (_songInfoTransitionStoryboard is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_songInfoTransitionStoryboard.Completed -= SongInfoTransitionStoryboard_Completed;
|
|
||||||
_songInfoTransitionStoryboard.Stop();
|
|
||||||
_songInfoTransitionStoryboard = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrent(TimeSpan current) =>
|
public string GetCurrent(TimeSpan current) =>
|
||||||
@@ -390,10 +273,4 @@ public sealed partial class RootPlayBarView : UserControl
|
|||||||
var dialog = new PropertiesDialog(currentSong!) { XamlRoot = XamlRoot };
|
var dialog = new PropertiesDialog(currentSong!) { XamlRoot = XamlRoot };
|
||||||
await dialog.ShowAsync();
|
await dialog.ShowAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RootPlayBarView_Unloaded(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
Data.PlayState.PropertyChanged -= OnStateChanged;
|
|
||||||
StopSongInfoTransition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user