using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media.Animation; using System.Windows.Threading; using System.Windows.Ink; namespace Ink_Canvas.Helpers { /// /// 墨迹渐隐管理器 - 管理墨迹的渐隐动画和状态 /// public class InkFadeManager { #region Properties /// /// 是否启用墨迹渐隐功能 /// public bool IsEnabled { get; set; } = false; /// /// 墨迹渐隐时间(毫秒) /// public int FadeTime { get; set; } = 3000; /// /// 渐隐动画持续时间(毫秒) /// public int AnimationDuration { get; set; } = 1000; #endregion #region Private Fields private readonly MainWindow _mainWindow; private readonly Dispatcher _dispatcher; private readonly Dictionary _fadeTimers; private readonly Dictionary _strokeVisuals; #endregion #region Constructor public InkFadeManager(MainWindow mainWindow) { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); _dispatcher = _mainWindow.Dispatcher; _fadeTimers = new Dictionary(); _strokeVisuals = new Dictionary(); } #endregion #region Public Methods /// /// 添加需要渐隐的墨迹 /// /// 墨迹对象 /// 墨迹的视觉元素 public void AddFadingStroke(Stroke stroke, UIElement visual) { if (!IsEnabled || stroke == null || visual == null) return; try { // 记录墨迹和视觉元素的对应关系 _strokeVisuals[stroke] = visual; // 创建定时器,在指定时间后开始渐隐动画 var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(FadeTime) }; timer.Tick += (sender, e) => { StartFadeAnimation(stroke); timer.Stop(); _fadeTimers.Remove(stroke); }; _fadeTimers[stroke] = timer; timer.Start(); // 将视觉元素添加到画布上 _dispatcher.InvokeAsync(() => { try { if (_mainWindow.inkCanvas != null) { _mainWindow.inkCanvas.Children.Add(visual); } } catch (Exception ex) { LogHelper.WriteLogToFile($"添加墨迹视觉元素到画布失败: {ex}", LogHelper.LogType.Error); } }); } catch (Exception ex) { LogHelper.WriteLogToFile($"添加渐隐墨迹失败: {ex}", LogHelper.LogType.Error); } } /// /// 移除墨迹 /// /// 要移除的墨迹 public void RemoveStroke(Stroke stroke) { if (stroke == null) return; try { if (_fadeTimers.TryGetValue(stroke, out var timer)) { timer.Stop(); _fadeTimers.Remove(stroke); } if (_strokeVisuals.TryGetValue(stroke, out var visual)) { _dispatcher.InvokeAsync(() => { try { if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual)) { _mainWindow.inkCanvas.Children.Remove(visual); } } catch (Exception ex) { LogHelper.WriteLogToFile($"从画布移除墨迹视觉元素失败: {ex}", LogHelper.LogType.Error); } }); _strokeVisuals.Remove(stroke); } } catch (Exception ex) { LogHelper.WriteLogToFile($"移除渐隐墨迹失败: {ex}", LogHelper.LogType.Error); } } /// /// 清除所有渐隐墨迹 /// public void ClearAllFadingStrokes() { try { foreach (var timer in _fadeTimers.Values) { timer.Stop(); } _fadeTimers.Clear(); _dispatcher.InvokeAsync(() => { try { if (_mainWindow.inkCanvas != null) { foreach (var visual in _strokeVisuals.Values) { if (_mainWindow.inkCanvas.Children.Contains(visual)) { _mainWindow.inkCanvas.Children.Remove(visual); } } } } catch (Exception ex) { LogHelper.WriteLogToFile($"清除所有墨迹视觉元素失败: {ex}", LogHelper.LogType.Error); } }); _strokeVisuals.Clear(); } catch (Exception ex) { LogHelper.WriteLogToFile($"清除所有渐隐墨迹失败: {ex}", LogHelper.LogType.Error); } } /// /// 更新渐隐时间设置 /// /// 新的渐隐时间(毫秒) public void UpdateFadeTime(int fadeTime) { FadeTime = fadeTime; foreach (var kvp in _fadeTimers) { var stroke = kvp.Key; var timer = kvp.Value; timer.Stop(); timer.Interval = TimeSpan.FromMilliseconds(FadeTime); timer.Start(); } } /// /// 更新动画持续时间设置 /// /// 新的动画持续时间(毫秒) public void UpdateAnimationDuration(int animationDuration) { AnimationDuration = animationDuration; } #endregion #region Private Methods /// /// 开始渐隐动画 /// /// 要渐隐的墨迹 private void StartFadeAnimation(Stroke stroke) { if (!_strokeVisuals.TryGetValue(stroke, out var visual)) return; try { _dispatcher.InvokeAsync(() => { var fadeAnimation = new DoubleAnimation { From = 1.0, To = 0.0, Duration = TimeSpan.FromMilliseconds(AnimationDuration), EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } }; fadeAnimation.Completed += (sender, e) => { try { if (_mainWindow.inkCanvas != null && _mainWindow.inkCanvas.Children.Contains(visual)) { _mainWindow.inkCanvas.Children.Remove(visual); } RemoveStroke(stroke); } catch (Exception ex) { LogHelper.WriteLogToFile($"渐隐动画完成后清理墨迹失败: {ex}", LogHelper.LogType.Error); } }; visual.BeginAnimation(UIElement.OpacityProperty, fadeAnimation); }); } catch (Exception ex) { LogHelper.WriteLogToFile($"开始渐隐动画失败: {ex}", LogHelper.LogType.Error); } } #endregion } }