0

我正在使用 AvalonEdit 创建一个 ANSI 终端,该终端可以正确地进行颜色编码并实现一些样式,如下划线和反转(它非常适用,这不是完整的 VT100 类型的东西)。

在 AvalonEdit 中将DocumentColorizingTransformerANSI 颜色代码转换为彩色文本或样式文本。昨晚我正在努力实现 ANSI Blink。我在使用这部分代码时眨了眨眼:

else if (color.AnsiColor is Blink)
{
    // The color animation of the pulse, use the opacity to simulate blinking
    var da = new DoubleAnimation
    {
        Duration = new Duration(TimeSpan.FromMilliseconds(500)),
        From = 0,
        To = 1,
        AutoReverse = true
        RepeatBehavior = RepeatBehavior.Forever
    };

    // Get the foreground
    var foreground = element.TextRunProperties.ForegroundBrush;

    // Clone the foreground so it's not frozen and we can run animations on it.
    var blinkForeground = foreground.Clone();

    // Set the new foreground.
    element.TextRunProperties.SetForegroundBrush(blinkForeground);

    // Blink Blink Blink Blink
    blinkForeground.BeginAnimation(SolidColorBrush.OpacityProperty, da);
}

显然,我希望此文本在屏幕上时永远闪烁,这就是我将 RepeatBehavior 设置为永远的原因。但是,即使它从屏幕的可见部分滚动出来,它也会继续使用 CPU(它可能没有渲染,但动画似乎仍在运行)。

我的问题:

当一段文本滚动出可见视图时,如何停止一段文本上的动画(不一定要通过 AvalonEdit 框中的所有内容,这可能非常非常大,而且在性能方面不可行) . 如果我可以在动画离开屏幕时停止动画,然后在ColorizeLine(DocumentLine line)触发时重新启动它,那将是理想的。使用 AvalonEdit,我知道什么时候通过ColorizeLine它是可见的,但那时我不一定知道什么是不可见的。我考虑保留对所有双重动画的引用列表,但我仍然不知道它们何时在屏幕上可见。

关于我如何解决这个问题的任何其他想法或想法?

4

1 回答 1

1

如果有任何动画正在运行,WPF 将以每秒 60 帧的速度呈现。如果没有实际更改,则渲染相对较快,但当应用程序应该处于空闲状态时,它仍然会导致明显的 CPU 使用率。AvalonEdit 的插入符号(使用计时器)切换为开关,而不是使用动画来避免渲染不必要的帧。


在 中DocumentColorizingTransformer,您可以使用this.CurrentContext.VisualLine来访问VisualLine正在处理的。有VisualLine一个IsDisposed属性,true一旦 AvalonEdit 丢弃该行(如果该行再次可见,将再次调用您的着色器)。

没有事件告诉您线路何时被处置。但是,如果您在列表中跟踪所有动画+它们包含VisualLine的 s,则可以使用该TextView.VisualLinesChanged事件来扫描VisualLine已处置的 s 并停止相应的动画。

于 2020-05-14T18:17:43.817 回答