improve:PPT时间胶囊
动画改进
This commit is contained in:
@@ -70,9 +70,9 @@
|
|||||||
<Storyboard x:Key="CapsuleExpandAnimation" x:Name="CapsuleExpandStoryboard">
|
<Storyboard x:Key="CapsuleExpandAnimation" x:Name="CapsuleExpandStoryboard">
|
||||||
<DoubleAnimation Storyboard.TargetName="MainCapsule"
|
<DoubleAnimation Storyboard.TargetName="MainCapsule"
|
||||||
Storyboard.TargetProperty="(FrameworkElement.Width)"
|
Storyboard.TargetProperty="(FrameworkElement.Width)"
|
||||||
Duration="0:0:0.3">
|
Duration="0:0:0.6">
|
||||||
<DoubleAnimation.EasingFunction>
|
<DoubleAnimation.EasingFunction>
|
||||||
<CubicEase EasingMode="EaseOut"/>
|
<BackEase EasingMode="EaseOut" Amplitude="0.4"/>
|
||||||
</DoubleAnimation.EasingFunction>
|
</DoubleAnimation.EasingFunction>
|
||||||
</DoubleAnimation>
|
</DoubleAnimation>
|
||||||
</Storyboard>
|
</Storyboard>
|
||||||
@@ -81,9 +81,9 @@
|
|||||||
<Storyboard x:Key="CapsuleShrinkAnimation" x:Name="CapsuleShrinkStoryboard">
|
<Storyboard x:Key="CapsuleShrinkAnimation" x:Name="CapsuleShrinkStoryboard">
|
||||||
<DoubleAnimation Storyboard.TargetName="MainCapsule"
|
<DoubleAnimation Storyboard.TargetName="MainCapsule"
|
||||||
Storyboard.TargetProperty="(FrameworkElement.Width)"
|
Storyboard.TargetProperty="(FrameworkElement.Width)"
|
||||||
Duration="0:0:0.3">
|
Duration="0:0:0.8">
|
||||||
<DoubleAnimation.EasingFunction>
|
<DoubleAnimation.EasingFunction>
|
||||||
<CubicEase EasingMode="EaseIn"/>
|
<BackEase EasingMode="EaseOut" Amplitude="0.2"/>
|
||||||
</DoubleAnimation.EasingFunction>
|
</DoubleAnimation.EasingFunction>
|
||||||
</DoubleAnimation>
|
</DoubleAnimation>
|
||||||
</Storyboard>
|
</Storyboard>
|
||||||
|
|||||||
@@ -22,15 +22,17 @@ namespace Ink_Canvas.Windows
|
|||||||
public partial class PPTTimeCapsule : UserControl
|
public partial class PPTTimeCapsule : UserControl
|
||||||
{
|
{
|
||||||
private System.Timers.Timer timeUpdateTimer;
|
private System.Timers.Timer timeUpdateTimer;
|
||||||
private System.Timers.Timer countdownUpdateTimer; // 倒计时更新定时器(参考MinimizedTimerControl)
|
private System.Timers.Timer countdownUpdateTimer;
|
||||||
private DateTime lastTime = DateTime.MinValue;
|
private DateTime lastTime = DateTime.MinValue;
|
||||||
private TimerControl parentControl; // 父计时器控件引用(参考MinimizedTimerControl)
|
private TimerControl parentControl;
|
||||||
private bool wasTimerRunning = false; // 上次检查时计时器是否运行
|
private bool wasTimerRunning = false;
|
||||||
private bool isOvertime = false;
|
private bool isOvertime = false;
|
||||||
private Storyboard capsuleExpandStoryboard;
|
private Storyboard capsuleExpandStoryboard;
|
||||||
private Storyboard capsuleShrinkStoryboard;
|
private Storyboard capsuleShrinkStoryboard;
|
||||||
private Storyboard colonBlinkStoryboard;
|
private Storyboard colonBlinkStoryboard;
|
||||||
private double originalCapsuleWidth = 0;
|
private double originalCapsuleWidth = 0;
|
||||||
|
private string lastCountdownText = ""; // 上次的倒计时文本,用于检测文本变化
|
||||||
|
private Storyboard currentWidthAnimation; // 当前正在运行的宽度动画
|
||||||
|
|
||||||
public PPTTimeCapsule()
|
public PPTTimeCapsule()
|
||||||
{
|
{
|
||||||
@@ -312,7 +314,7 @@ namespace Ink_Canvas.Windows
|
|||||||
{
|
{
|
||||||
if (parentControl == null) return;
|
if (parentControl == null) return;
|
||||||
|
|
||||||
// 检查计时器是否正在运行(参考MinimizedTimerControl)
|
// 检查计时器是否正在运行
|
||||||
bool isRunning = parentControl.IsTimerRunning;
|
bool isRunning = parentControl.IsTimerRunning;
|
||||||
|
|
||||||
// 如果状态改变,更新UI
|
// 如果状态改变,更新UI
|
||||||
@@ -325,6 +327,7 @@ namespace Ink_Canvas.Windows
|
|||||||
CountdownPanel.Visibility = Visibility.Visible;
|
CountdownPanel.Visibility = Visibility.Visible;
|
||||||
// 确保倒计时文本使用主题颜色
|
// 确保倒计时文本使用主题颜色
|
||||||
ApplyTheme();
|
ApplyTheme();
|
||||||
|
UpdateCountdownText();
|
||||||
PlayCapsuleExpandAnimation();
|
PlayCapsuleExpandAnimation();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -356,8 +359,34 @@ namespace Ink_Canvas.Windows
|
|||||||
var timeSpan = remainingTime.Value;
|
var timeSpan = remainingTime.Value;
|
||||||
bool isOvertimeMode = timeSpan.TotalSeconds < 0;
|
bool isOvertimeMode = timeSpan.TotalSeconds < 0;
|
||||||
|
|
||||||
|
// 更新倒计时文本
|
||||||
|
UpdateCountdownText(timeSpan, isOvertimeMode);
|
||||||
|
|
||||||
|
// 根据文本内容动态调整胶囊宽度
|
||||||
|
AdjustCapsuleWidthToContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新倒计时文本内容
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateCountdownText(TimeSpan? timeSpan = null, bool? isOvertimeMode = null)
|
||||||
|
{
|
||||||
|
if (CountdownText == null || parentControl == null) return;
|
||||||
|
|
||||||
|
if (!timeSpan.HasValue)
|
||||||
|
{
|
||||||
|
var remainingTime = parentControl.GetRemainingTime();
|
||||||
|
if (!remainingTime.HasValue) return;
|
||||||
|
timeSpan = remainingTime.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isOvertimeMode.HasValue)
|
||||||
|
{
|
||||||
|
isOvertimeMode = timeSpan.Value.TotalSeconds < 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 处理超时状态
|
// 处理超时状态
|
||||||
if (isOvertimeMode)
|
if (isOvertimeMode.Value)
|
||||||
{
|
{
|
||||||
if (!isOvertime)
|
if (!isOvertime)
|
||||||
{
|
{
|
||||||
@@ -373,7 +402,7 @@ namespace Ink_Canvas.Windows
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 显示超时时间
|
// 显示超时时间
|
||||||
var overtimeSpan = -timeSpan;
|
var overtimeSpan = -timeSpan.Value;
|
||||||
if (overtimeSpan.TotalHours >= 1)
|
if (overtimeSpan.TotalHours >= 1)
|
||||||
{
|
{
|
||||||
int hours = (int)overtimeSpan.TotalHours;
|
int hours = (int)overtimeSpan.TotalHours;
|
||||||
@@ -412,18 +441,92 @@ namespace Ink_Canvas.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeSpan.TotalHours >= 1)
|
if (timeSpan.Value.TotalHours >= 1)
|
||||||
{
|
{
|
||||||
int hours = (int)timeSpan.TotalHours;
|
int hours = (int)timeSpan.Value.TotalHours;
|
||||||
CountdownText.Text = $"{hours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}";
|
CountdownText.Text = $"{hours:D2}:{timeSpan.Value.Minutes:D2}:{timeSpan.Value.Seconds:D2}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CountdownText.Text = $"{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}";
|
CountdownText.Text = $"{timeSpan.Value.Minutes:D2}:{timeSpan.Value.Seconds:D2}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据内容动态调整胶囊宽度
|
||||||
|
/// </summary>
|
||||||
|
private void AdjustCapsuleWidthToContent()
|
||||||
|
{
|
||||||
|
if (MainCapsule == null || !wasTimerRunning || CountdownText == null) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查文本是否改变(格式变化可能导致宽度变化)
|
||||||
|
string currentText = CountdownText.Text;
|
||||||
|
if (currentText == lastCountdownText)
|
||||||
|
{
|
||||||
|
// 文本未改变,不需要调整
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCountdownText = currentText;
|
||||||
|
|
||||||
|
double currentWidth = MainCapsule.ActualWidth;
|
||||||
|
double targetWidth = CalculateTargetWidth();
|
||||||
|
|
||||||
|
// 如果当前宽度与目标宽度差异较大(超过2像素),则调整
|
||||||
|
if (Math.Abs(currentWidth - targetWidth) > 2)
|
||||||
|
{
|
||||||
|
// 停止当前动画
|
||||||
|
if (currentWidthAnimation != null)
|
||||||
|
{
|
||||||
|
currentWidthAnimation.Stop();
|
||||||
|
currentWidthAnimation = null;
|
||||||
|
}
|
||||||
|
if (capsuleExpandStoryboard != null)
|
||||||
|
{
|
||||||
|
capsuleExpandStoryboard.Stop();
|
||||||
|
}
|
||||||
|
if (capsuleShrinkStoryboard != null)
|
||||||
|
{
|
||||||
|
capsuleShrinkStoryboard.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新的动画
|
||||||
|
var animation = new DoubleAnimation
|
||||||
|
{
|
||||||
|
From = currentWidth,
|
||||||
|
To = targetWidth,
|
||||||
|
Duration = new Duration(TimeSpan.FromMilliseconds(targetWidth > currentWidth ? 600 : 800)),
|
||||||
|
EasingFunction = targetWidth > currentWidth
|
||||||
|
? new BackEase { EasingMode = EasingMode.EaseOut, Amplitude = 0.4 }
|
||||||
|
: new BackEase { EasingMode = EasingMode.EaseOut, Amplitude = 0.2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
var storyboard = new Storyboard();
|
||||||
|
Storyboard.SetTarget(animation, MainCapsule);
|
||||||
|
Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.WidthProperty));
|
||||||
|
storyboard.Children.Add(animation);
|
||||||
|
currentWidthAnimation = storyboard;
|
||||||
|
storyboard.Begin();
|
||||||
|
|
||||||
|
storyboard.Completed += (o, args) =>
|
||||||
|
{
|
||||||
|
storyboard.Remove();
|
||||||
|
if (currentWidthAnimation == storyboard)
|
||||||
|
{
|
||||||
|
currentWidthAnimation = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"调整胶囊宽度失败: {ex.Message}", LogHelper.LogType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void PlayCapsuleExpandAnimation()
|
private void PlayCapsuleExpandAnimation()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -436,8 +539,15 @@ namespace Ink_Canvas.Windows
|
|||||||
originalCapsuleWidth = MainCapsule.ActualWidth > 0 ? MainCapsule.ActualWidth : 120;
|
originalCapsuleWidth = MainCapsule.ActualWidth > 0 ? MainCapsule.ActualWidth : 120;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算目标宽度(根据倒计时文本长度估算)
|
// 停止当前动画
|
||||||
double targetWidth = originalCapsuleWidth + 80; // 增加约80像素用于显示倒计时
|
if (currentWidthAnimation != null)
|
||||||
|
{
|
||||||
|
currentWidthAnimation.Stop();
|
||||||
|
currentWidthAnimation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据倒计时文本的实际宽度动态计算目标宽度
|
||||||
|
double targetWidth = CalculateTargetWidth();
|
||||||
|
|
||||||
if (capsuleExpandStoryboard == null)
|
if (capsuleExpandStoryboard == null)
|
||||||
{
|
{
|
||||||
@@ -450,7 +560,7 @@ namespace Ink_Canvas.Windows
|
|||||||
var animation = capsuleExpandStoryboard.Children[0] as DoubleAnimation;
|
var animation = capsuleExpandStoryboard.Children[0] as DoubleAnimation;
|
||||||
if (animation != null)
|
if (animation != null)
|
||||||
{
|
{
|
||||||
animation.From = originalCapsuleWidth;
|
animation.From = MainCapsule.ActualWidth;
|
||||||
animation.To = targetWidth;
|
animation.To = targetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,12 +574,52 @@ namespace Ink_Canvas.Windows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据倒计时文本的实际宽度计算目标宽度
|
||||||
|
/// </summary>
|
||||||
|
private double CalculateTargetWidth()
|
||||||
|
{
|
||||||
|
if (CountdownText == null || TimeDisplayPanel == null)
|
||||||
|
{
|
||||||
|
// 如果倒计时文本不可用,使用估算值
|
||||||
|
return originalCapsuleWidth + 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测量倒计时文本的实际宽度
|
||||||
|
CountdownText.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||||
|
double countdownTextWidth = CountdownText.DesiredSize.Width;
|
||||||
|
|
||||||
|
// 测量时间显示面板的宽度
|
||||||
|
TimeDisplayPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||||
|
double timeDisplayWidth = TimeDisplayPanel.DesiredSize.Width;
|
||||||
|
|
||||||
|
double targetWidth = timeDisplayWidth + countdownTextWidth + 8 + 32;
|
||||||
|
|
||||||
|
// 确保最小宽度不小于原始宽度
|
||||||
|
if (targetWidth < originalCapsuleWidth)
|
||||||
|
{
|
||||||
|
targetWidth = originalCapsuleWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetWidth;
|
||||||
|
}
|
||||||
|
|
||||||
private void PlayCapsuleShrinkAnimation()
|
private void PlayCapsuleShrinkAnimation()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (MainCapsule != null && originalCapsuleWidth > 0)
|
if (MainCapsule != null && originalCapsuleWidth > 0)
|
||||||
{
|
{
|
||||||
|
// 停止当前动画
|
||||||
|
if (currentWidthAnimation != null)
|
||||||
|
{
|
||||||
|
currentWidthAnimation.Stop();
|
||||||
|
currentWidthAnimation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置文本跟踪
|
||||||
|
lastCountdownText = "";
|
||||||
|
|
||||||
if (capsuleShrinkStoryboard == null)
|
if (capsuleShrinkStoryboard == null)
|
||||||
{
|
{
|
||||||
capsuleShrinkStoryboard = (Storyboard)Resources["CapsuleShrinkAnimation"];
|
capsuleShrinkStoryboard = (Storyboard)Resources["CapsuleShrinkAnimation"];
|
||||||
|
|||||||
Reference in New Issue
Block a user