簡體   English   中英

使用VisualBrush時WPF故事板動畫問題

[英]WPF storyboard animation issue when using VisualBrush

我當時正在使用情節提要,翻轉動畫和可視筆刷。 我遇到了一個問題。 下面是一個小樣本的xaml和代碼隱藏,我迅速將它們放在一起以嘗試演示該問題。

首次啟動該應用程序時,會顯示一個紅色正方形和兩個按鈕。 如果單擊“翻轉”按鈕,則紅色方塊將“翻轉”,並且將出現藍色方塊。 實際上,所有發生的事情是紅色正方形所在的StackPanel的寬度比例被減小,直到達到零為止,然后是藍色正方形所在的StackPanel,其寬度最初被縮放為零,然后將其變為寬度增加。 如果單擊“翻轉”按鈕幾次,動畫將看起來正常且流暢。

現在,如果您單擊“ Reflection”按鈕,則將紅色/藍色按鈕的反射添加到它們各自的StackPanels中。 現在點擊“翻轉”按鈕仍將導致翻轉動畫,但不再是平滑動畫。 StackPanels的寬度通常不會縮小為零。 寬度有所縮小,但在完全不可見之前就停止了。 然后另一個StackPanel照常出現。 唯一更改的是添加了反射,這只是一個VisualBrush。

下面是代碼。 有誰知道為什么這兩種情況之間的動畫不同(在第二種情況下是靜止的)?

謝謝。

<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xml:lang="en-US"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
 x:Class="WpfFlipTest.Window1"
 x:Name="Window"
 Title="Window1"
 Width="214" Height="224">
  <Window.Resources>
    <Storyboard x:Key="sbFlip">
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="redStack"  Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.4" Value="0"/>
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetName="blueStack" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.8" Value="1"/>
      </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="sbFlipBack">
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="blueStack"  Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.4" Value="0"/>
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetName="redStack" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.8" Value="1"/>
      </DoubleAnimationUsingKeyFrames>
    </Storyboard>
  </Window.Resources>
  <Grid x:Name="LayoutRoot" Background="Gray">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <StackPanel Name="redStack" Grid.Row="0" Grid.Column="0" RenderTransformOrigin="0.5,0.5">
      <StackPanel.RenderTransform>
        <ScaleTransform/>
      </StackPanel.RenderTransform>
      <Border Name="redBorder" BorderBrush="Transparent" BorderThickness="4" Width="Auto" Height="Auto">
        <Button Margin="0" Name="redButton" Height="75" Background="Red" Width="105" />
      </Border>
      <Border Width="{Binding ElementName=redBorder, Path=ActualWidth}" 
              Height="{Binding ElementName=redBorder, Path=ActualHeight}" 
              Opacity="0.2" BorderBrush="Transparent" BorderThickness="4" Name="redRefelction" Visibility="Collapsed">
        <Border.OpacityMask>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
              <GradientStop Offset="0" Color="Black"/>
              <GradientStop Offset=".6" Color="Transparent"/>
            </LinearGradientBrush.GradientStops>
          </LinearGradientBrush>
        </Border.OpacityMask>
        <Border.Background>
          <VisualBrush Visual="{Binding ElementName=redButton}">
            <VisualBrush.Transform>
              <ScaleTransform ScaleX="1" ScaleY="-1" 
                CenterX="52.5" 
                CenterY="37.5" />
            </VisualBrush.Transform>
          </VisualBrush>
        </Border.Background>
      </Border>
    </StackPanel>
    <StackPanel Name="blueStack" Grid.Row="0" Grid.Column="0" RenderTransformOrigin="0.5,0.5">
      <StackPanel.RenderTransform>
        <ScaleTransform ScaleX="0"/>
      </StackPanel.RenderTransform>
      <Border Name="blueBorder" BorderBrush="Transparent" BorderThickness="4" Width="Auto" Height="Auto">
        <Button Grid.Row="0" Grid.Column="1" Margin="0" Width="105" Background="Blue" Name="blueButton" Height="75"/>
      </Border>
      <Border Width="{Binding ElementName=blueBorder, Path=ActualWidth}" 
              Height="{Binding ElementName=blueBorder, Path=ActualHeight}" 
              Opacity="0.2" BorderBrush="Transparent" BorderThickness="4" Name="blueRefelction" Visibility="Collapsed">
        <Border.OpacityMask>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
              <GradientStop Offset="0" Color="Black"/>
              <GradientStop Offset=".6" Color="Transparent"/>
            </LinearGradientBrush.GradientStops>
          </LinearGradientBrush>
        </Border.OpacityMask>
        <Border.Background>
          <VisualBrush Visual="{Binding ElementName=blueButton}">
            <VisualBrush.Transform>
              <ScaleTransform ScaleX="1" ScaleY="-1" 
                CenterX="52.5" 
                CenterY="37.5" />
            </VisualBrush.Transform>
          </VisualBrush>
        </Border.Background>
      </Border>
    </StackPanel>
    <Button Grid.Row="1" Click="FlipButton_Click" Height="19.45" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76">Flip</Button>
    <Button Grid.Row="0" Grid.Column="1" Click="ReflectionButton_Click" Height="19.45" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76">Reflection</Button>
  </Grid>
</Window>

以下是按鈕單擊處理程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace WpfFlipTest
{
  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
    }

    bool flipped = false;
    private void FlipButton_Click(object sender, RoutedEventArgs e)
    {
      Storyboard sbFlip = (Storyboard)Resources["sbFlip"];
      Storyboard sbFlipBack = (Storyboard)Resources["sbFlipBack"];

      if (flipped)
      {
        sbFlipBack.Begin();
        flipped = false;
      }
      else
      {
        sbFlip.Begin();
        flipped = true;
      }
    }

    bool reflection = false;
    private void ReflectionButton_Click(object sender, RoutedEventArgs e)
    {
      if (reflection)
      {
        reflection = false;
        redRefelction.Visibility = Visibility.Collapsed;
        blueRefelction.Visibility = Visibility.Collapsed;
      }
      else
      {
        reflection = true;
        redRefelction.Visibility = Visibility.Visible;
        blueRefelction.Visibility = Visibility.Visible;
      }
    }
  }
}







更新:

我已經對此進行了更多測試,以試圖找出導致我看到的問題的原因,並且我相信我已經找到了導致問題的原因。

在下面,我粘貼了新的xaml,並在其后面添加了代碼。 下面的新示例與原始示例非常相似,但做了一些小的修改。 xaml基本上由兩個堆棧面板組成,每個面板包含兩個邊框。 每個堆棧面板中的第二個邊框是可視畫筆(其上方邊框的反射)。 現在,當我單擊“翻轉”按鈕時,一個堆棧面板將其ScaleX減小為零,而第二個堆棧面板(其初始ScaleX為零)將其ScaleX增大為1。此動畫給人以翻轉的感覺。 還有兩個文本塊顯示每個堆棧面板的比例因子。 我添加了這些內容以嘗試診斷我的問題。

問題是(如口頭文章中所述)翻轉動畫不流暢。 每次我按下翻轉按鈕時,動畫都會開始,但是每當ScaleX因子達到.14到.16左右時,動畫就好像停滯了,並且堆棧面板上的ScaleX從未降為零,因此它們從未完全消失。 現在,奇怪的是,如果我更改下面定義的“ frontBorder”和“ backBorder”邊框的Width / Height屬性,以使用顯式值而不是Auto,例如Width = 105和Height = 75(以匹配按鈕邊界),一切正常。 動畫在開始運行前兩到三次時會口吃,但是之后的翻轉是平滑無瑕的。 (順便說一句,當第一次運行動畫時,背景中是否正在發生某種事情,是否進行了某種初始化,從而使動畫在第一次運行時有點慢?)

邊框的自動寬度/高度是否可能導致此問題? 我可以每次重現它,但是我不確定為什么自動寬度/高度會成為問題。

下面是示例。 謝謝您的幫助。

<Window x:Class="FlipTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
  <Window.Resources>
    <Storyboard x:Key="sbFlip">
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="front"  Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0"/>
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.5" Storyboard.TargetName="back" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
      </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key="sbFlipBack">
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="back"  Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="0"/>
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.5" Storyboard.TargetName="front" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
        <SplineDoubleKeyFrame KeyTime="00:00:00.5" Value="1"/>
      </DoubleAnimationUsingKeyFrames>
    </Storyboard>
  </Window.Resources>
  <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <StackPanel x:Name="front" RenderTransformOrigin="0.5,0.5">
      <StackPanel.RenderTransform>
        <ScaleTransform/>
      </StackPanel.RenderTransform>
      <Border Name="frontBorder" BorderBrush="Yellow" BorderThickness="2" Width="Auto" Height="Auto">
        <Button Margin="0" Name="redButton" Height="75" Background="Red" Width="105" Click="FlipButton_Click"/>
      </Border>
      <Border Width="{Binding ElementName=frontBorder, Path=ActualWidth}" 
              Height="{Binding ElementName=frontBorder, Path=ActualHeight}" 
              Opacity="0.2" BorderBrush="Transparent">
        <Border.OpacityMask>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
              <GradientStop Offset="0" Color="Black"/>
              <GradientStop Offset=".6" Color="Transparent"/>
            </LinearGradientBrush.GradientStops>
          </LinearGradientBrush>
        </Border.OpacityMask>
        <Border.Background>
          <VisualBrush Visual="{Binding ElementName=frontBorder}">
            <VisualBrush.Transform>
              <ScaleTransform ScaleX="1" ScaleY="-1" 
                CenterX="52.5" 
                CenterY="37.5" />
            </VisualBrush.Transform>
          </VisualBrush>
        </Border.Background>
      </Border>
    </StackPanel>
    <StackPanel x:Name="back" RenderTransformOrigin="0.5,0.5">
      <StackPanel.RenderTransform>
        <ScaleTransform ScaleX="0"/>
      </StackPanel.RenderTransform>
      <Border Name="backBorder" BorderBrush="Yellow" BorderThickness="2" Width="Auto" Height="Auto">
        <Button Margin="0" Width="105" Background="Blue" Name="blueButton" Height="75" Click="FlipButton_Click"/>
      </Border>
      <Border Width="{Binding ElementName=backBorder, Path=ActualWidth}" 
              Height="{Binding ElementName=backBorder, Path=ActualHeight}" 
              Opacity="0.2" BorderBrush="Transparent">
        <Border.OpacityMask>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
              <GradientStop Offset="0" Color="Black"/>
              <GradientStop Offset=".6" Color="Transparent"/>
            </LinearGradientBrush.GradientStops>
          </LinearGradientBrush>
        </Border.OpacityMask>
        <Border.Background>
          <VisualBrush Visual="{Binding ElementName=backBorder}">
            <VisualBrush.Transform>
              <ScaleTransform ScaleX="1" ScaleY="-1" 
                CenterX="52.5" 
                CenterY="37.5" />
            </VisualBrush.Transform>
          </VisualBrush>
        </Border.Background>
      </Border>
    </StackPanel>
    <Button Grid.Row="1" Click="FlipButton_Click" Height="19.45" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76">Flip</Button>
    <TextBlock Grid.Row="2" Grid.Column="0" Foreground="DarkRed" Height="19.45" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76" Text="{Binding ElementName=front, Path=(UIElement.RenderTransform).(ScaleTransform.ScaleX)}"/>
    <TextBlock Grid.Row="3" Grid.Column="0" Foreground="DarkBlue" Height="19.45" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76" Text="{Binding ElementName=back, Path=(UIElement.RenderTransform).(ScaleTransform.ScaleX)}"/>
  </Grid>
</Window>

后台代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace FlipTest
{
  /// <summary>
  /// Interaction logic for Window1.xaml
  /// </summary>
  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
    }

    bool flipped = false;
    private void FlipButton_Click(object sender, RoutedEventArgs e)
    {
      Storyboard sbFlip = (Storyboard)Resources["sbFlip"];
      Storyboard sbFlipBack = (Storyboard)Resources["sbFlipBack"];

      if (flipped)
      {
        sbFlipBack.Begin();
        flipped = false;
      }
      else
      {
        sbFlip.Begin();
        flipped = true;
      }
    }
  }
}

我在新的x64機器上再次嘗試了此操作,動畫運行順利,沒有任何問題。 我之前看到的內容一定與舊計算機性能不佳有關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM