もくじ
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f
やりたいこと
WPFアプリで簡単なアニメーションを実装したいときに<Storyboard>をよく使うが、その書き方、特に動かし方(アニメーションのStartのさせ方)にいろいろあり、覚えられないので一旦まとめておきたい。
(Storyboardの「Startのさせ方」のみまとめる。Storyboard自体の使い方やできることは今回はやらない)
■ 書き方別/目的別 Storyboardの書き方
どういう書き方をしたいか、どういうときにStoryboardでアニメ―ションしたいかで、サンプルとなるコードをまとめた。
★Storyboardを書きたい場所
- 対象コントロールの中に直接書く
Resourcesの中にまとめて書く
★目的別
- 単純な使い方(アプリ起動したらずっと動かしておきたい等)
- 対象Controlのイベント(MouseDown等)発生時に動かしたい(xamlのみ)
- ViewModel等のプロパティの変化時に動かしたい(xamlのみ)
- コードの中から動かしたい(xaml+cs)
■①対象コントロールの中に直接書く
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:AnimationTest"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"><Rectanglex:Name="MyRect"Stroke="Red"StrokeThickness="5"Width="100"Height="100"RenderTransformOrigin="0.5 0.5"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Loaded"><BeginStoryboard><StoryboardRepeatBehavior="Forever"Timeline.DesiredFrameRate="30"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetName="MyRect"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:01.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle></Window>■②Resourcesの中にまとめて書く
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:AnimationTest"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"><Window.Resources><Storyboardx:Key="MyRoundingAnimation"RepeatBehavior="Forever"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:00.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></Window.Resources><Rectanglex:Name="MyRect"Stroke="Red"StrokeThickness="5"Width="100"Height="100"RenderTransformOrigin="0.5 0.5"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Loaded"><BeginStoryboardStoryboard="{StaticResource MyRoundingAnimation}"/></EventTrigger></Rectangle.Triggers></Rectangle></Window>■③styleの中に書く/コントロールのプロパティ(IsMouseOver等)の変化でStart
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:AnimationTest"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"Name="root"><Window.Resources><Storyboardx:Key="MyRoundingAnimation"RepeatBehavior="1"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:00.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></Window.Resources><Grid><RectangleStroke="Red"StrokeThickness="3"RenderTransformOrigin="0.5 0.5"Fill="Aqua"Margin="50"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform><Rectangle.Style><StyleTargetType="Rectangle"><Style.Triggers><TriggerProperty="IsMouseOver"Value="True"><Trigger.EnterActions><BeginStoryboardStoryboard="{StaticResource MyRoundingAnimation}"Name="bsb"/></Trigger.EnterActions><Trigger.ExitActions><StopStoryboardBeginStoryboardName="bsb"/></Trigger.ExitActions></Trigger></Style.Triggers></Style></Rectangle.Style></Rectangle></Grid></Window>※<Style.Triggers>の中で、<Trigger Property="IsMouseOver" Value="True">を書くことはできたが、<RectAngle.Triggers>の中に<Trigger Property="IsMouseOver" Value="True">を書くことはできなかった。
(Triggersの中はEventTriggerでないといけない、と怒られる)
■④ViewModel等のプロパティの変化でStart
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:AnimationTest"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"Name="root"><Window.Resources><Storyboardx:Key="MyRoundingAnimation"RepeatBehavior="1"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:00.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></Window.Resources><Grid><!-- このチェックボックスがプロパティをONOFFする --><CheckBoxIsChecked="{Binding Chk, ElementName=root}"/><RectangleStroke="Red"StrokeThickness="3"RenderTransformOrigin="0.5 0.5"Margin="50"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform><Rectangle.Style><StyleTargetType="Rectangle"><Style.Triggers><!-- プロパティのONOFFでStoryBoardを動かしたり止めたりする --><DataTriggerBinding="{Binding Chk, ElementName=root}"Value="True"><DataTrigger.EnterActions><BeginStoryboardStoryboard="{StaticResource MyRoundingAnimation}"Name="bsb"/></DataTrigger.EnterActions><DataTrigger.ExitActions><StopStoryboardBeginStoryboardName="bsb"/></DataTrigger.ExitActions></DataTrigger></Style.Triggers></Style></Rectangle.Style></Rectangle></Grid></Window>■⑤ViewModel等のプロパティの変化でStart(別解)
Blend SDK for WPFに同梱されているBehaviorというのを使う。
参考:https://blog.okazuki.jp/category/XAML?page=1419259848
下記で行った準備が必要。(参照の追加)
https://qiita.com/tera1707/items/7ecde6e97a19437cbf72#eventtrigger%E3%82%92%E4%BD%BF%E3%81%86
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"xmlns:local="clr-namespace:AnimationTest"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"Name="root"><Window.Resources><Storyboardx:Key="MyRoundingAnimation"RepeatBehavior="Forever"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetName="MyRect"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:00.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></Window.Resources><!-- プロパティのONOFFでStoryboardを制御 --><i:Interaction.Triggers><ei:DataTriggerBinding="{Binding Chk, ElementName=root}"Value="true"><ei:DataTrigger.Actions><ei:ControlStoryboardActionControlStoryboardOption="Play"Storyboard="{StaticResource MyRoundingAnimation}"/></ei:DataTrigger.Actions></ei:DataTrigger><ei:DataTriggerBinding="{Binding Chk, ElementName=root}"Value="false"><ei:DataTrigger.Actions><ei:ControlStoryboardActionControlStoryboardOption="Stop"Storyboard="{StaticResource MyRoundingAnimation}"/></ei:DataTrigger.Actions></ei:DataTrigger></i:Interaction.Triggers><Grid><!-- このチェックボックスがプロパティをONOFFする --><CheckBoxIsChecked="{Binding Chk, ElementName=root}"/><Rectanglex:Name="MyRect"Stroke="Red"StrokeThickness="3"RenderTransformOrigin="0.5 0.5"Margin="50"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform></Rectangle></Grid></Window>■⑥c#コードの中からStart
MainWindow.xaml
<Windowx:Class="AnimationTest.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"Title="MainWindow"Height="300"Width="300"Name="root"><Window.Resources><Storyboardx:Key="MyRoundingAnimation"RepeatBehavior="Forever"><DoubleAnimationUsingKeyFramesBeginTime="00:00:00"Storyboard.TargetName="MyRect"Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)"><LinearDoubleKeyFrameKeyTime="00:00:00.5"Value="360"/></DoubleAnimationUsingKeyFrames></Storyboard></Window.Resources><Grid><ToggleButtonContent="ボタン"HorizontalAlignment="Left"VerticalAlignment="Top"Click="ToggleButton_Click"/><Rectanglex:Name="MyRect"Stroke="Red"StrokeThickness="3"RenderTransformOrigin="0.5 0.5"Margin="50"><Rectangle.RenderTransform><TransformGroup><RotateTransformAngle="0"/></TransformGroup></Rectangle.RenderTransform></Rectangle></Grid></Window>MainWindow.xaml.cs
usingSystem.Windows;usingSystem.Windows.Controls.Primitives;usingSystem.Windows.Media.Animation;namespaceAnimationTest{publicpartialclassMainWindow:Window{publicMainWindow(){InitializeComponent();}privatevoidToggleButton_Click(objectsender,RoutedEventArgse){// StoryBoardを検索varsb=FindResource("MyRoundingAnimation")asStoryboard;// トグルボタンを押すたびにstart/stopするif(senderisToggleButtontb){if(tb.IsChecked.Value)sb.Begin();elsesb.Stop();}}}}