我在玩故事板、翻转动画和视觉画笔。虽然我遇到了一个问题。下面是我快速拼凑的一个小示例的 xaml 和代码隐藏,以尝试演示该问题。
首次启动应用程序时,您会看到一个红色方块和两个按钮。如果单击“翻转”按钮,红色方块将“翻转”并出现蓝色方块。实际上,正在发生的所有事情是红色方块所在的 StackPanel 的宽度比例正在减小,直到它达到零,然后蓝色方块所在的 StackPanel(其宽度最初缩放为零)具有宽度增加。如果您单击“翻转”按钮几次,动画看起来还不错且流畅。
现在,如果您点击“反射”按钮,红色/蓝色按钮的反射将添加到它们各自的 StackPanel 中。现在点击“翻转”按钮仍会导致翻转动画,但不再是流畅的动画。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 因子达到 0.14 到 0.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;
}
}
}
}