編集: プロジェクトはここからダウンロードできます。
私は WPF Storyboard を使用して地球の回転をアニメーション化しています。ユーザーがボタンをクリックしたときに、回転を時計回りから反時計回り (およびその逆) に反転できるようにしたいのですが、実際にはこれは決して起こらないはずです。
私の XAML ファイルでは、21 個の BitmapImages (最初と最後は同一) と 2 つの Storyboards を宣言します。1 つは時計回りの回転用で、もう 1 つは反時計回りの回転用です。
<Window x:Class="StackOverflowWPF.StoryboardSeekWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StoryboardSeekWindow" Height="400" Width="400">
<Window.Resources>
<BitmapImage x:Key="RotationImage0" UriSource="Images\rotation\0.png"/>
<BitmapImage x:Key="RotationImage1" UriSource="Images\rotation\1.png"/>
<BitmapImage x:Key="RotationImage2" UriSource="Images\rotation\2.png"/>
<BitmapImage x:Key="RotationImage3" UriSource="Images\rotation\3.png"/>
<BitmapImage x:Key="RotationImage4" UriSource="Images\rotation\4.png"/>
<BitmapImage x:Key="RotationImage5" UriSource="Images\rotation\5.png"/>
<BitmapImage x:Key="RotationImage6" UriSource="Images\rotation\6.png"/>
<BitmapImage x:Key="RotationImage7" UriSource="Images\rotation\7.png"/>
<BitmapImage x:Key="RotationImage8" UriSource="Images\rotation\8.png"/>
<BitmapImage x:Key="RotationImage9" UriSource="Images\rotation\9.png"/>
<BitmapImage x:Key="RotationImage10" UriSource="Images\rotation\10.png"/>
<BitmapImage x:Key="RotationImage11" UriSource="Images\rotation\11.png"/>
<BitmapImage x:Key="RotationImage12" UriSource="Images\rotation\12.png"/>
<BitmapImage x:Key="RotationImage13" UriSource="Images\rotation\13.png"/>
<BitmapImage x:Key="RotationImage14" UriSource="Images\rotation\14.png"/>
<BitmapImage x:Key="RotationImage15" UriSource="Images\rotation\15.png"/>
<BitmapImage x:Key="RotationImage16" UriSource="Images\rotation\16.png"/>
<BitmapImage x:Key="RotationImage17" UriSource="Images\rotation\17.png"/>
<BitmapImage x:Key="RotationImage18" UriSource="Images\rotation\18.png"/>
<BitmapImage x:Key="RotationImage19" UriSource="Images\rotation\19.png"/>
<BitmapImage x:Key="RotationImage20" UriSource="Images\rotation\20.png"/>
<Storyboard x:Key="clockwiseStoryboard" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="imgRotatingEarth" Storyboard.TargetProperty="Source">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{Binding Source={StaticResource RotationImage0}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="{Binding Source={StaticResource RotationImage1}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4" Value="{Binding Source={StaticResource RotationImage2}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.6" Value="{Binding Source={StaticResource RotationImage3}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{Binding Source={StaticResource RotationImage4}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.0" Value="{Binding Source={StaticResource RotationImage5}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.2" Value="{Binding Source={StaticResource RotationImage6}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.4" Value="{Binding Source={StaticResource RotationImage7}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.6" Value="{Binding Source={StaticResource RotationImage8}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.8" Value="{Binding Source={StaticResource RotationImage9}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.0" Value="{Binding Source={StaticResource RotationImage10}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.2" Value="{Binding Source={StaticResource RotationImage11}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.4" Value="{Binding Source={StaticResource RotationImage12}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.6" Value="{Binding Source={StaticResource RotationImage13}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.8" Value="{Binding Source={StaticResource RotationImage14}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.0" Value="{Binding Source={StaticResource RotationImage15}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.2" Value="{Binding Source={StaticResource RotationImage16}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.4" Value="{Binding Source={StaticResource RotationImage17}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.6" Value="{Binding Source={StaticResource RotationImage18}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.8" Value="{Binding Source={StaticResource RotationImage19}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:4.0" Value="{Binding Source={StaticResource RotationImage20}}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="counterClockwiseStoryboard" RepeatBehavior="Forever">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="imgRotatingEarth" Storyboard.TargetProperty="Source">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{Binding Source={StaticResource RotationImage20}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.2" Value="{Binding Source={StaticResource RotationImage19}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.4" Value="{Binding Source={StaticResource RotationImage18}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.6" Value="{Binding Source={StaticResource RotationImage17}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.8" Value="{Binding Source={StaticResource RotationImage16}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.0" Value="{Binding Source={StaticResource RotationImage15}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.2" Value="{Binding Source={StaticResource RotationImage14}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.4" Value="{Binding Source={StaticResource RotationImage13}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.6" Value="{Binding Source={StaticResource RotationImage12}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1.8" Value="{Binding Source={StaticResource RotationImage11}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.0" Value="{Binding Source={StaticResource RotationImage10}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.2" Value="{Binding Source={StaticResource RotationImage9}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.4" Value="{Binding Source={StaticResource RotationImage8}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.6" Value="{Binding Source={StaticResource RotationImage7}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2.8" Value="{Binding Source={StaticResource RotationImage6}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.0" Value="{Binding Source={StaticResource RotationImage5}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.2" Value="{Binding Source={StaticResource RotationImage4}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.4" Value="{Binding Source={StaticResource RotationImage3}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.6" Value="{Binding Source={StaticResource RotationImage2}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:3.8" Value="{Binding Source={StaticResource RotationImage1}}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:4.0" Value="{Binding Source={StaticResource RotationImage0}}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid>
<Image x:Name="imgRotatingEarth" HorizontalAlignment="Center" Margin="50" Stretch="Uniform" />
<Button VerticalAlignment="Bottom" Content="Reverse" Height="30" Width="100" Click="reverseButton_Click" />
</Grid>
そして私のコードビハインドファイル
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.Shapes;
using System.Windows.Media.Animation;
namespace StackOverflowWPF
{
/// <summary>
/// Interaction logic for StoryboardSeekWindow.xaml
/// </summary>
public partial class StoryboardSeekWindow : Window
{
Storyboard clockwiseStoryboard;
Storyboard counterClockwiseStoryboard;
bool bRotateClockwisely;
TimeSpan duration = new TimeSpan(0, 0, 4);
double dProgress = 0; //the value of dProgress is from 0.0 (begin) to 1.0 (end)
public StoryboardSeekWindow()
{
InitializeComponent();
clockwiseStoryboard = this.FindResource("clockwiseStoryboard") as Storyboard;
counterClockwiseStoryboard = this.FindResource("counterClockwiseStoryboard") as Storyboard;
StartRotation();
}
private void StartRotation()
{
counterClockwiseStoryboard.Begin();
counterClockwiseStoryboard.Pause();
clockwiseStoryboard.Begin();
bRotateClockwisely = true;
}
private void reverseButton_Click(object sender, RoutedEventArgs e)
{
Storyboard sbActive = bRotateClockwisely ? clockwiseStoryboard : counterClockwiseStoryboard;
Storyboard sbPaused = bRotateClockwisely ? counterClockwiseStoryboard : clockwiseStoryboard;
sbActive.Pause();
//I want the other storyboard can seek to where the animation is paused.
dProgress = sbActive.GetCurrentProgress();
dProgress = 1.0 - dProgress;
sbPaused.Seek(new TimeSpan((long)(duration.Ticks * dProgress)));
sbPaused.Resume();
bRotateClockwisely = !bRotateClockwisely;
}
}
}
時計回りモードから反時計回りモードへのスムーズな遷移を得るために、アクティブなアニメーションを一時停止し、どのフレームにいるのかを計算します。リバース アニメーションを再開するときは、最初にそのフレームをシークします。つまり、効果を出したい。
0.png->1.png->2.png->3.png->4.png->5.png->ユーザーがボタンをクリック->5.png->4.png->3.png-> 2.png->1.png->0.png->...
しかし、私のコードは機能しません。Storyboard.Seek() は動作しているようですが、逆回転しません。同じオブジェクトを操作するために 2 つのストーリーボードを実行するのは間違っていると思います。
誰かがバグを修正するのを手伝ってくれませんか?おそらく同じ効果を達成するためのより良いアイデアを提供してくれますか?