WPF Storyboard播放多个DoubleAnimation出现卡顿

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF Storyboard播放多个DoubleAnimation出现卡顿相关的知识,希望对你有一定的参考价值。

有一个DoubleAnimation的List,在Storyboard的Completed中不断给Storyboard加入DoubleAnimation。然后根据动画的轨迹在Canvas上描出动画轨迹经过的点,但是在动画切换的时候出现卡顿,怎么解决

参考技术A 没有贴代码,以下只能猜测。
两个方向:动画的处理方式是否可以优化,动画轨迹的点处理是否可以优化?
DoubleAnimation的List,是否使用的是同一个Storyboard实例?
如果是,是否在Storyboard的Completed之后清除了已经完成DoubleAnimation?
如果不清除,将会导致Storyboard每次要处理的Animation不断累积。

可以缩减DoubleAnimation的集合的长度,观察执行效果,查看动画轨迹的处理是否影响动画。追问

  

您好,这是代码,您的意思是每次触发Completed事件都将Storyboard中的Animation清除掉是么?listlistDAUP是动画的集合

追答

看代码,story是Storyboard的实例,全局的。
如果在上一次动画完成后不清除story的Animation集合,story的Animation会将之前执行过的DoubleAnimation再执行一遍,这样所有播放过的动画,会在后面的播放动作中再播放一次,直至集合遍历结束,你可以设置断点查看story的Children的情况。
不知道,这样设计是否为了达到某个目的?还是说可以通过其他途径达到你要的效果?

追问

补充一下,我是通过用动画去移动button,然后在获取button的坐标,就把改点给画出来,上面说的有些是需要画出来,有些不用的意思是button依然在移动,但是后台进行判断该点需不需要被画出来。

追答

你想实现的效果是类似粉笔在黑板上画线,要有粉笔及轨迹(button和button移动),在需要的地方要有笔迹(Path中需要画出来的线段),假如是这样的需求,如下代码
画线动画,结合一个Button轨迹,如果只需要Button轨迹去掉line即可:
private void DrawLineAnimation(double x1, double y1, double x2, double y2)
Line line = new Line();
Button btn = new Button();
btn.Width = 12;
btn.Height = 12;
btn.Background = Brushes.Red;
Canvas.SetLeft(btn, x1 - btn.Width / 2);
Canvas.SetTop(btn, y1 - btn.Height / 2);
_RootLayout.Children.Add(line); //_RootLayout 为动画容器
_RootLayout.Children.Add(btn);
Storyboard sbLine = new Storyboard();//For Line 动画定义省略...
Storyboard sbBtn = new Storyboard();//For Button 动画定义省略...
sbLine.Completed += sbLine_Completed; //声明动画结束事件
sbBtn.Completed += sbBtn_Completed;
line.BeginStoryboard(sbLine);
btn.BeginStoryboard(sbBtn);

这段代码是是我实现画线动画的部分长度限制动画定义部分省略了,Button是结合补充内容加上去的。通过递归修改索引的方式遍历线段集,就可以把Path路径画出来。

本回答被提问者和网友采纳

WPF 内部Template 动画板 无法冻结此 Storyboard 时间线树供跨线程使用

原文:WPF 内部Template 动画板 无法冻结此 Storyboard 时间线树供跨线程使用

解决此问题,需要一定的想象力。

换个思路即可

大体是

使用Tag或者别无用的可以输入数值的属性,或者附加属性也可以的。来绑定到你要动画的属性

当然这个过程中要使用转换器了

我给出一个关于Button 的Width的内部模板小栗子,各位朋友可以针对自己的项目/控件进行修改

 

XAML代码

技术图片
    <Window.Resources>
        <local:ToCon x:Key="To"/>
        <Style x:Key="FocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
        <SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
        <SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
        <SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
        <SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
        <SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
        <SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
        <SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
        <SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
        <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
            <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
            <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <ControlTemplate.Resources>
                            <local:ToCon  x:Key="ToConHeight"/>
                        </ControlTemplate.Resources>
                        <Border  Height="{Binding Tag,RelativeSource={RelativeSource Mode=Self},  Converter={ StaticResource ToConHeight }}" x:Name="border"  BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                            <Border.Tag>
                                <Binding Path="Tag" RelativeSource="{RelativeSource Mode=TemplatedParent}" Converter="{StaticResource ToConHeight }"/>
                            </Border.Tag>
                            <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsDefaulted" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation  Storyboard.TargetProperty="Tag" To="200" Duration="0:0:2"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Style="{DynamicResource ButtonStyle1}" Tag="{Binding Width ,
            RelativeSource={RelativeSource Mode=Self},
            Converter={StaticResource ResourceKey=To}}" Width="100" Background="Red">

        </Button>
    </Grid>
技术图片

 

 

转换器

技术图片
    public class ToCon : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return 0;
            return  double.Parse(value.ToString());
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value.ToString();
        }
    }
}
技术图片

 

 

截图

技术图片

以上是关于WPF Storyboard播放多个DoubleAnimation出现卡顿的主要内容,如果未能解决你的问题,请参考以下文章

WPF如何后台改变动画触发器绑定值

wpf 动画执行的问题

wpf Storyboard 不存在可解析名称“ ”的适用名称领域

WPF - 无法停止动画 StoryBoard,IsControllable 不起作用?

2021-09-25 WPF上位机 42-Storyboard

WPF - 将滑块值数据绑定到 StoryBoard?