如何在 UWP 的文本块中对多个"Run"元素的前景属性进行动画处理?



我有这段代码。这只是一个例子。我想用代码来做。如何设置多个"前景"属性的动画;运行";TextBlock中的元素?

<Page
x:Class="AnimationTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:AnimationTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<TextBlock
x:Name="_textBlockElement"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="72"><Run x:Name="_run1" Text="Hel" /><Run Text="lo" />
<TextBlock.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard x:Name="ColorStoryboard">
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetName="_textBlockElement"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Red"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Grid>
</Page>

好的,所以这需要一些整理,但事实证明是可行的。

关键是用正确的动画在代码背后创建两个序列图板,然后将这些序列图板添加到Run的任何父级的资源中。

让我们从XAML代码开始,它非常简单:

<Grid>
<TextBlock x:Name="TestBlock"
HorizontalAlignment="Center" VerticalAlignment="Center"
PointerEntered="TestBlock_PointerEntered"
PointerExited="TestBlock_PointerExited">
<Run x:Name="Run1" Text="Test1" Foreground="Blue"/>
<Run x:Name="Run2" Text="Test2" Foreground="Green"/>
<!-- ... -->
</TextBlock>
</Grid>

为了简单起见,我已经定义了Run的名称和前景。

现在我们需要在代码背后定义故事板和动画
我选择在构造函数中执行此操作(InitializeComponent()之后!(。理论上,您还应该能够在Page_Loaded事件中粘贴此代码。

public MainPage()
{
InitializeComponent();
SetupStoryBoards();
}
void SetupStoryBoards()
{
// Define duration and storyboards to red and original color
var duration = new Duration(TimeSpan.FromSeconds(1));
var toRedStory = new Storyboard { Duration = duration };
// completed events can be subscribed to, to register when animation is done
//toRedStory.Completed += Story_Completed;
var toOriginalStory = new Storyboard { Duration = duration };
//toOriginalStory.Completed += ToOriginalStory_Completed;
foreach (Run r in TestBlock.Inlines)
{
// Filter out any inlines that are not a named Run
if (string.IsNullOrEmpty(r.Name))
continue;
// Define the animations
var toRedAnim = new ColorAnimation
{
Duration = duration,
To = Colors.Red,
EnableDependentAnimation = true
};
var toOriginalAnim = new ColorAnimation
{
Duration = duration,
To = (r.Foreground as SolidColorBrush).Color, // Causes animation to go back to original foreground color of Run
EnableDependentAnimation = true
};
// Add animations to the storyboards and associate animations with the Run
toRedStory.Children.Add(toRedAnim);
toOriginalStory.Children.Add(toOriginalAnim);
Storyboard.SetTargetName(toRedAnim, r.Name);
Storyboard.SetTargetName(toOriginalAnim, r.Name);
Storyboard.SetTargetProperty(toRedAnim, "(Run.Foreground).(SolidColorBrush.Color)");
Storyboard.SetTargetProperty(toOriginalAnim, "(Run.Foreground).(SolidColorBrush.Color)");
}
// Add the storyboards to the resources of any parent of the Run's for easy retrieval later and to make the animations find the Run's
// I choose the resources of the textblock that contains the Run's
TestBlock.Resources.Add("toRedStory", toRedStory);
TestBlock.Resources.Add("toOriginalStory", toOriginalStory);
}

现在,为了执行动画,我们添加了PointerEnteredPointerExited事件处理程序,并在那里开始正确的故事板:

private void TextBlock_PointerEntered(object sender, PointerRoutedEventArgs e)
{
var story = TestBlock.Resources["toRedStory"] as Storyboard;
story.Begin();
}
private void TextBlock_PointerExited(object sender, PointerRoutedEventArgs e)
{
var story = TestBlock.Resources["toOriginalStory"] as Storyboard;
story.Begin();
}

您应该能够在任何需要的地方扩展它,但是我发现EnableDependentAnimation必须设置为true,否则它将不起作用。

最新更新