Bir önceki makalemizde
Windows
Prensetation Foundation(WPF) uygulamalarında animasyon işlemlerinin
temel animasyon tipleri
(Basic Animation Types) yardımıyla nasıl
gerçekleştirilebileceğini incelemeye başlamıştık. Bu makalemizde
animasyon işlemleri üzerindeki yönetimin biraz daha fazla olmasını
sağlamak için farklı teknikleri göz önüne alıyor olacağız. Her zaman
olduğu gibi konuyu daha iyi kavrayabilmek adına örnekler üzerinden
ilerlemekte fayda olduğu kanısındayım. Dilerseniz hiç vakit kaybetmeden
ilk örneğimiz ile başalayım. Hatırlanacağı üzere, WPF uygulamalarında
bileşenlerin rotasyon işlemleri için
RotateTransform,
ScaleTransform ve benzeri tiplerin kullanıldığını görmüştük. Bu tip
transformasyon işlemlerini animasyon tipleri ile birlikte kullanmak
isteyebiliriz. Söz gelimi bir Button kontrolünün 3 saniye içerisinde
kendi ekseninde 360 derece dönmesini ve bu sırada boyutlarınında 2
katına çıkarak tekrardan eski haline dönmesini istediğimizi düşünelim.
Bu tip bir animasyon işleminin Buttton kontrolünün üzerine mouse ile
gelindiğinde başlatılmasını ve 3 saniyelik zaman dilimi içerisinde mouse
ile kontrolün terk edilmesi halinde de durmasınıda sağlayabiliriz.
Burada temel animasyon tiplerinden olan
DoubleAnimation oldukça
işe yarayacaktır. Herşeyden önce animasyon tipinin RotateTransform ve
ScaleTransform tiplerindeki uygun özellikleri kontrol edecek şekilde
ayarlanması gerekir. Bu senaryoyu gerçekleştirmek için
XAML
içeriği aşağıda verilen bir pencere(Window) oluşturulması yeterli
olacaktır.

XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.RotateAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Rotate ve Sacle Animasyon" Height="220" Width="289">
<Grid>
<Button Name="btnMerhaba" Width="75"
Height="40" Content="Merhaba" Background="Gold"
Foreground="Black" FontSize="14" FontWeight="Bold">
<Button.LayoutTransform>
<TransformGroup>
<RotateTransform x:Name="RTrans" Angle="0"/>
<ScaleTransform x:Name="STrans" CenterX="0" CenterY="0"
ScaleX="1" ScaleY="1"/>
</TransformGroup>
</Button.LayoutTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Name="strBrd">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="RTrans" Storyboard.TargetProperty="Angle"
To="360" Duration="0:0:3"/>
<DoubleAnimation Storyboard.TargetName="STrans"
Storyboard.TargetProperty="ScaleX" To="2.5" Duration="0:0:1.5"/>
<DoubleAnimation
Storyboard.TargetName="STrans"
Storyboard.TargetProperty="ScaleY" To="2.5" Duration="0:0:1.5"/>
<DoubleAnimation
Storyboard.TargetName="STrans"
Storyboard.TargetProperty="ScaleX" To="1" Duration="0:0:3"/>
<DoubleAnimation Storyboard.TargetName="STrans"
Storyboard.TargetProperty="ScaleY" To="1" Duration="0:0:3"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="strBrd"/>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</Window>
Burada dikkat edilmesi gereken
noktalardan birisi, RotateTransform ve ScaleTransform
elementlerinin DoubleAnimation tiplerinde kullanılabilmesi için
x:Name nitelikleri ile isimlendirilmiş olmalarıdır. Diğer
taraftan RotateTransform, Button bileşenin verilen açı kadar
döndürülmesini sağlamaktadır. Buna göre ilk DoubleAnimation
elementi 3 saniyelik zaman çizgisi(TimeLine) içerisinde açının
değerinin 360 derece olmasını sağlamaktadır. Sonrasında gelen dört
DoubleAnimation tipi ise ilk 1.5 saniyelik zaman dilimi içerisinde
ScaleTransform elementinin ScaleX ve ScaleY
değerlerini önce iki buçuk katına çıkarmakta sonrasında ise tekrar eski
haline döndürmektedir. Söz konusu animasyon işlemleri MouseEnter
olayı tetiklendiğinde başlatılmaktadır. Diğer taraftan MouseLeave
olayı tetiklendiğinde, bir başka deyişle mouse ile Button kontrolü
üzerinden çıkıldığında animasyon işlemi durdurulmaktadır. Durdurma
işlemi için StopStroyboard elementi kullanılır. Bu elementin
hangi animasyon işlemini durduracağını belirtmek için
BeginStroyboardName niteliğine(attribute) ilgili değerin atanması
gerekir. Örneğimizde bu değer, BeginStroyboard elementindeki
Name niteliğinin değeri olan strBrd' dir. Buna göre istersek birden
fazla Storyboard' un olduğu bir senaryoda Name niteliğinden yararlanarak
hangisinin durdurulacağını, duraksatılacağını(Pause) yada
çıkartılacağını(Remove) belirleyebiliriz.
NOT: WPF(Windows Presentation
Foundation) mimarisinde farklı Storyboard tipleri vardır.
- BeginStoryboard
: Storyboard' un başlatılmasını sağlar.
- PauseStoryboard
: Storyboard duraksatılır.
- ResumeStoryboard
: Duraksatılan storyboard kaldığı yerden devam eder.
- RemoveStoryboard
: Storyboard kaldırılır.
-
SetStoryboardSpeedRatio : Storyboard içerisinde
animasyonların hız oranı değiştirilebilir.
- SkipStoryboardToFill
: Eğer Stroyboard içerisinde tanımlanmış bir Fill periyodu
varsa animasyonun otomatik olarak buraya atlaması sağlanır.
Örneği yürüttüğümüzde çalışma zamanında(Run-time)
aşağıdaki Flash görselinde yer alan etkileri izleyebiliriz. (Flash
dosyasının boyutu 264 Kb olduğundan yüklenmesi zaman alabilir.
Dosyanın boyutunun küçük olması için kalitesi düşürülmüştür. Bu nedenle
kitap animasyon hareketi sırasında iz bırakmaktadır. Gerçek uygulamada
elbetteki böyle bir iz yoktur.)
Benzer işlemleri kod tarafında yapmakta
oldukça kolaydır. Bunun için aşağıdaki kodlara ve XAML içeriğine sahip
pencereyi ele alabiliriz.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaRotateAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kodla Rotate Animasyon" Height="250" Width="325">
<Grid>
<Button
Name="btnMerhaba"
Width="75" Height="40" Content="Merhaba" Background="Black"
Foreground="Gold" FontSize="14" FontWeight="Bold">
<Button.
LayoutTransform>
<
TransformGroup>
<
RotateTransform
x:Name="RTrans"
Angle="0"/>
<
ScaleTransform
x:Name="STrans"
CenterX="0" CenterY="0"
ScaleX="1"
ScaleY="1"/>
</
TransformGroup>
</Button.
LayoutTransform>
</Button>
</Grid>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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;
// Animasyon tiplerinin yer aldığı isim alanıdır(Namespace)
namespace AnimasyonIslemleri
{
public partial class KodlaRotateAnimasyon : Window
{
private void AnimasyonuOlustur()
{
// Storyboard
oluşturulur
Storyboard strBrd
= new Storyboard();
// Birinci
DoubleAnimation tipi oluşturulur.
// İlk
parametre To değeridir ve burada 360 dereceyi işaret etmektedir.
İkinci parametre ise Duration değeridir.
DoubleAnimation
dblAni1 = new DoubleAnimation(360, new
Duration(TimeSpan.FromSeconds(3)));
// Animasyon
tipinin RTrans adına sahip elementin AngleProperty özelliğine
uygulanacağı belirtilir.
Storyboard.SetTargetName(dblAni1,
"RTrans");
Storyboard.SetTargetProperty(dblAni1,
new PropertyPath(RotateTransform.AngleProperty));
// Animasyon
tipi Storyboard' a eklenir.
s
trBrd.Children.Add(dblAni1);
// İkinci
DoubleAnimation tipi oluşturulur.
// İlk
parametre To değeridir ve burada 2.5 katını işaret etmektedir.
İkinci parametre ise Duration değeridir. Buna göre zaman
çizgisinin ilk 1.5 saniyesi içerisinde Button bileşeninin ScaleX
değeri 2.5 kat artmaktadır.
DoubleAnimation dblAni2 = new DoubleAnimation(2.5, new
Duration(TimeSpan.FromSeconds(1.5)));
// Animayonun
STrans isimli ScaleTransform elementi içerisindeki ScaleX
özelliğine uygulanacağı belirtilir.
Storyboard.
SetTargetName(dblAni2,
"STrans");
Storyboard.
SetTargetProperty(dblAni2,
new PropertyPath(ScaleTransform.ScaleXProperty));
// Animasyon
tipi Storyboard' a eklenir.
strBrd.
Children.Add(dblAni2);
// Üçüncü
DoubleAnimation tipi oluşturulur.
// İlk
parametre To değeridir ve burada 2.5 katını işaret etmektedir.
İkinci parametre ise Duration değeridir. Buna göre zaman
çizgisinin ilk 1.5 saniyesi içerisinde Button bileşeninin ScaleY
değeri 2.5 kat artmaktadır.
DoubleAnimation dblAni3 = new DoubleAnimation(2.5, new
Duration(TimeSpan.FromSeconds(1.5)));
// Animayonun
STrans isimli ScaleTransform elementi içerisindeki ScaleY
özelliğine uygulanacağı belirtilir.
Storyboard.SetTargetName(dblAni3,
"STrans");
Storyboard.SetTargetProperty(dblAni3,
new
PropertyPath(ScaleTransform.ScaleYProperty));
// Animasyon
tipi Storyboard' a eklenir.
strBrd.
Children.Add(dblAni3);
// Zaman
çizgisinin 3ncü saniyesine gelindiğinde Button kontrolünün
ScaleX değeri ilk haline döner.
DoubleAnimation dblAni4 = new DoubleAnimation(1, new
Duration(TimeSpan.FromSeconds(3)));
Storyboard.SetTargetName(dblAni4,
"STrans");
Storyboard.SetTargetProperty(dblAni4,
new
PropertyPath(ScaleTransform.ScaleXProperty));
// Animasyon
tipi Storyboard' a eklenir.
strBrd.
Children.Add(dblAni4);
// Zaman
çizgisinin 3ncü saniyesine gelindiğinde Button kontrolünün
ScaleY değeri ilk haline döner.
DoubleAnimation dblAni5 = new DoubleAnimation(1, new
Duration(TimeSpan.FromSeconds(3)));
Storyboard.SetTargetName(dblAni5, "STrans");
Storyboard.SetTargetProperty(dblAni5, new
PropertyPath(ScaleTransform.ScaleYProperty));
// Animasyon
tipi Storyboard' a eklenir.
strBrd.
Children.Add(dblAni5);
// Mouse ile
Button alanı üzerinde gelindiğinde animasyon başlatılır.
btnMerhaba.
MouseEnter
+= delegate(object sender, MouseEventArgs e)
{
/* İkinci parametre Storyboard' un kontrol edilebileceğini
gösterir. Bir başka deyişle programatik olarak animasyonun
durdurulması, duraksatılması ve benzeri işlemlerin yapılabilmesi
sağlanır. */
strBrd.Begin(this,true);
};
btnMerhaba.
MouseLeave
+= delegate(object sender, MouseEventArgs e)
{
// Storyboard' un başlattığı animasyon çıkartılır. Dolayısıyla
Button açısal konum ve büyüklük olarak ilk değerlerine döner.
strBrd.Stop(this);
};
}
public KodlaRotateAnimasyon()
{
InitializeComponent();
AnimasyonuOlustur();
}
}
}
Kod yapısında dikkat edilmesi gereken
önemli noktalardan birisi, MouseLeave olayının gerçekleşmesi
halinde var olan amimasyonun durdurulması(Stop) işleminin
Storyboard nesne örneğine ait Stop metodu ile gerçekleştirimiş
olmasıdır. Lakin burada Stop metodunun işe yarayabilmesi için animasyon
Begin metodu ile başlatılırken ikinci parametrenin true olarak
verilmesi şarttır. Bu parametrenin true olarak verilmesi halinde
yanlızca Stop metodu değil, Pause, Resume,
Remove gibi yönetsel fonksiyonelliklerinde kullanılabilir hale
gelmesi sağlanmaktadır.
Animasyon işlemlerinde zaman çizgileri
(Timeline) içerisinde yer alan KeyFrame' lerin yönetilmesi
ve bu sayede daha güçlü hareketlerin sağlanabilmeside mümkündür. Bu
amaçla WPF yapısı içerisine 3 temel KeyFrame tipi konulmuştur.
Bunlar LinearDoubleKeyFrame, DiscreteDoubleKeyFrame,
SplineDoubleKeyFrame tipleridir. Söz konusu tiplerin ne şekilde
kullanıldıklarını örnekler ile incelediğimizde konuyu daha rahat
kavrayabiliriz. Sıradaki örneğimizde LinearDoubleKeyFrame tipini
kullanıyor olacağız. Bu amaçla ilk olarak aşağıdaki XAML
çıktısını içeren bir pencere (Window) hazırladığımızı düşünelim.
XAML içeriği;

<Window
x:Class="AnimasyonIslemleri.MerhabaKeyFrameAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Merhaba Key Frame Animasyon" Height="300" Width="300">
<Canvas>
<Rectangle
Name="Dortgen"
Canvas.Top="0"
Canvas.Left ="100"
Height="125" Width="93">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger
RoutedEvent="Rectangle.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Top)">
<LinearDoubleKeyFrame Value="160" KeyTime="0:0:2"/>
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:4"/>
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:6"/>
<LinearDoubleKeyFrame Value="40" KeyTime="0:0:8"/>
<LinearDoubleKeyFrame
Value="80" KeyTime="0:0:10"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Window>
Dikkat edileceği üzere örnekte
kullanılan LienarDoubleKeyFrame elementleri
DoubleAnimationUsingKeyFrames elementi içerisinde yer almaktadır.
Buna göre KeyFrame tiplerinin TipAdıUsingKeyFrames
notasyonu ile tanımlanmış tipler içerisinde olması gerektiği ortadadır.
Peki burada yer alan LinearDoubleKeyFrame elementleri ne işe
yaramaktadır?
Value özelliği ile tahmin
edileceği gibi DoubleAnimationUsingKeyFrames elementinde
belirtilen kontrol ve ilgili özelliğin yeni değeri belirlenir.
KeyTime niteliği ilede, özelliğin zaman çizelgesi içerisinde
belirtilen anda değerini alması sağlanır. Bir başka deyişle örnekte
kullanılan Dortgen isimli Rectangle elementinin pencerenin(Window)
üst kısmından olan uzaklığı, zaman çizelgesi(timeline) içerisinde
Frame noktalarında farklı değerlere set edilmektedir. Aslında durumu
daha iyi kavramak için pencerenin çalışma zamanındaki çıktısına bakmakta
fayda vardır. Aşağıdaki Flash animasyonunda bu durum işaret
edilmektedir.(Flash dosyasının boyutu 322 Kb
olduğundan yüklenmesi zaman alabilir. Dosyanın boyutunun
küçük olması için kalitesi düşürülmüştür. Bu nedenle kitap animasyon
hareketi sırasında iz bırakmaktadır. Gerçek uygulamada elbetteki böyle
bir iz yoktur.)
Görüldüğü gibi dörtgenimiz zaman
çizelgesinin 2nci saniyesinde pencerenin üst kenarının 160 piksel, 4ncü
saniyesinde tekrardan 0 piksel, 6ncı saniyesinde 100 piksel, 8nci
saniyesinde 40 piksel, 10ncu saniyesinde ise 80 piksel uzağına
gelmektedir. Sonrasında ise bu animasyon hareketini tersine doğru
yapmaktadır. Bunun için Storyboard elementinin AutoReverse
özelliğine true değerinin atanması yeterli olmaktadır. Durumu
aşağıdaki şekil ile daha net bir şekilde anlayabiliriz.

Aynı örneği kod yardımıylada
gerçekleştirebiliriz. Bunun için aşağıdaki XAML içeriğine ve kodlarına
sahip bir pencere(Window) geliştirmemiz yeterli olacaktır.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaMerhabaKeyFrameAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kodla Merhaba KeyFrame Animasyon" Height="241"
Width="218">
<Canvas x:Name="Bolge">
<Rectangle
Name="Dortgen"
Canvas.Top="0" Canvas.Left="65" Height="65" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
</Rectangle>
</Canvas>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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 AnimasyonIslemleri
{
public partial class KodlaMerhabaKeyFrameAnimasyon : Window
{
private void AnimasyonuHazirla()
{
//
DoubleAnimationKeyFrames nesnesi örneklenir.
DoubleAnimationUsingKeyFrames dblKeyFrames = new
DoubleAnimationUsingKeyFrames();
// Animasyon
tipi, kontrol ve özelliğini ilişkilendirecek olan StoryBoard
oluşturulur.
Storyboard strBrd
= new Storyboard();
// Animasyon
sona erdiğinde aynı rotadan geriye doğru dönmesi için
AutoReverse özelliğine true değeri atanır
strBrd.
AutoReverse
= true;
//
Animasyonun sürekli olması için RepeatBehavior özelliğine
Forever değeri atanır.
strBrd
.RepeatBehavior
= RepeatBehavior.Forever;
// Hedef
kontrol olarak Rectangle tipinden olan Dortgen seçilir
Storyboard.SetTargetName(dblKeyFrames, "Dortgen");
// Animasyon
değerlerinin uygulanacağı özellikl olarak Canvas' ın Top
özelliği seçilir.
Storyboard.SetTargetProperty(dblKeyFrames, new
PropertyPath(Canvas.TopProperty));
// KeyFrame
değerleri belirlenir.
// İlk 1
saniyede Canvas dikeylemesine 120 pikselinci uzaklığa gelecektir
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(120, KeyTime.FromTimeSpan(new TimeSpan(0,
0, 1))));
// 2nci
saniyede Canvas dikeylemesine 0 pikselinci uzaklığa gelecektir
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(new TimeSpan(0, 0,
2))));
// 3ncü
saniyede Canvas dikeylemesine 100 pikselinci uzaklığa gelecektir
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(100, KeyTime.FromTimeSpan(new TimeSpan(0,
0, 3))));
// 4ncü
saniyede Canvas dikeylemesine 50 pikselinci uzaklığa gelecektir
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(50, KeyTime.FromTimeSpan(new TimeSpan(0, 0,
4))));
// 5nci
saniyede Canvas dikeylemesine 75 pikselinci uzaklığa gelecektir.
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(75, KeyTime.FromTimeSpan(new TimeSpan(0, 0,
5))));
// 6nci
saniyede Canvas dikeylemesine 25 pikselinci uzaklığa gelecektir.
dblKeyFrames.
KeyFrames.Add(new
LinearDoubleKeyFrame(25, KeyTime.FromTimeSpan(new TimeSpan(0, 0,
6))));
// Animasyon
tipi StoryBoard nesnesine eklenir
strBrd.
Children.Add(dblKeyFrames);
//
Animasyonun, Mouse ile Dortgen in üzerine gelindiğinde başlaması
sağlanır.
Dortgen.
MouseEnter
+= delegate(object sender, MouseEventArgs e)
{
strBrd.Begin(this);
};
}
public
KodlaMerhabaKeyFrameAnimasyon()
{
InitializeComponent();
AnimasyonuHazirla();
}
}
}
Kod tarafında dikkat edilmesi gereken
noktalardan birisi LinearDoubleKeyFrame nesne örneklerinin
DoubleAnimationUsingKeyFrames tipinin KeyFrames koleksiyonunda
tutuluyor olmasıdır. KeyFrames özelliği üzerinden çağırılan
Add metodu ile ilgili nesnelerin koleksiyona eklenmesi sağlanır.
Oldukça eğlenceli değil mi? Gelin LinearDoubleKeyKeyFrame nesnelerinin
kullanıldığı başka bir örnek ile devam edelim. Bu yeni örnekte bir
öncekinden farklı olarak Canvas' ın Top ve Left
özelliklerini rastegele oranlarda değiştiriyor olacağız. İşte örnek XAML
içeriği ve kodlarımız.

XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaKeyFrameAnimasyon2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="KodlaKeyFrameAnimasyon2" Height="400" Width="400"
Background="LightBlue">
<Canvas
x:Name="alan">
<Rectangle
Name="dortgenim" Canvas.Top="0" Canvas.Left="0"
Height="65" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
</Rectangle>
</Canvas>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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 AnimasyonIslemleri
{
public partial class KodlaKeyFrameAnimasyon2 : Window
{
Random rnd = new
Random();
Storyboard strBrd
= new Storyboard();
public void AnimasyonuYurut()
{
double
randomT = rnd.Next(1, 250);
double randomL =
rnd.Next(1, 250);
Title=String.Format("İlk nokta {0}:{1} İkinci Nokta
{2}:{3}",randomT.ToString(),randomL.ToString(),(randomT -
25).ToString(),(randomL - 25).ToString());
strBrd.
AutoReverse
= false;
strBrd.
RepeatBehavior
= new RepeatBehavior(1);
DoubleAnimationUsingKeyFrames keyFrm1 = new
DoubleAnimationUsingKeyFrames();
keyFrm1.KeyFrames.Add(new LinearDoubleKeyFrame(randomT,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 3))));
keyFrm1.KeyFrames.Add(new LinearDoubleKeyFrame(randomT-25,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 5))));
Storyboard.SetTargetName(keyFrm1, "dortgenim");
Storyboard.SetTargetProperty(keyFrm1, new
PropertyPath(Canvas.TopProperty));
strBrd.Children.Add(keyFrm1);
DoubleAnimationUsingKeyFrames keyFrm2 = new
DoubleAnimationUsingKeyFrames();
keyFrm2.KeyFrames.Add(new
LinearDoubleKeyFrame(randomL, KeyTime.FromTimeSpan(new
TimeSpan(0, 0, 3))));
keyFrm2.KeyFrames.Add(new LinearDoubleKeyFrame(randomL-25,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 5))));
Storyboard.SetTargetName(keyFrm2, "dortgenim");
Storyboard.SetTargetProperty(keyFrm2, new
PropertyPath(Canvas.LeftProperty));
strBrd.Children.Add(keyFrm2);
strBrd.Begin(this);
}
void
dortgenim_MouseEnter(object
sender, MouseEventArgs e)
{
AnimasyonuYurut();
}
public KodlaKeyFrameAnimasyon2()
{
InitializeComponent();
dortgenim.MouseEnter += new
MouseEventHandler(dortgenim_MouseEnter);
}
}
}
Tahmin edileceği üzere dortgenin Top
ve Left özelliklerini animayon içerisinde kullanmak
istediğimizden iki farklı DoubleAnimationUsingKeyFrames nesne
örneği kullanılması gerekmektedir. Bu nesne örnekleride kendi içlerinde
farklı LinearDoubleKeyFrame nesnelerine sahiptir. Örneğin çalışma
zamanındaki(run-time) çıktısı aşağıdaki Flash görselindeki gibi
olacaktır. (Flash dosyasının boyutu 454 Kb
olduğundan yüklenmesi zaman alabilir. Dosyanın boyutunun
küçük olması için kalitesi düşürülmüştür. Bu nedenle kitap animasyon
hareketi sırasında iz bırakmaktadır. Gerçek uygulamada elbetteki böyle
bir iz yoktur.)
LinearDoubleKeyFrame tipi söz
konusu değerlere ulaşılırken akıcı bir görselliğin olmasını sağlar.
Bunun dışında DiscreteDoubleKeyFrame tipi kullanılaraktan
nesnenin belirtilen animasyonda bir sonraki değerine sıçrayarak geçmesi
sağlanabilir. Aslında bu durumu anlamanın en iyi yolu örnek bir senaryo
üzerinde ilerlemektir. Bu amaçla aşağıdaki XAML çıktısına sahip
bir pencere(Window) tasarladığımızı düşünelim.

XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.DiscreteKullanimi"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DiscreteDoubleKeyFrame ile Animasyon" Height="400"
Width="400">
<Canvas>
<Rectangle Name="Dortgen"
Canvas.Top="0" Canvas.Left="0" Height="75" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Top)">
<DiscreteDoubleKeyFrame KeyTime="0:0:1" Value="150"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:2" Value="30"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:3" Value="120"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:4" Value="60"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:5" Value="90"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:6" Value="75"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Left)">
<DiscreteDoubleKeyFrame KeyTime="0:0:1.5" Value="150"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:2.5" Value="30"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:3.5" Value="120"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:4.5" Value="60"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:5.5" Value="90"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:6.5" Value="75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Window>
Örnekte iki adet
DoubleAnimationUsingKeyFrames elementi kullanılmıştır. Bunlardan
birisi Canvas tipinin Top özelliği üzerinde diğeri ise
Left özelliği üzerinden animasyon işlemlerinin yürütülmesini
olanaklı kılmaktadır. Her biri kendi içerisinde birden fazla
DiscreteDoubleKeyFrame tipi içermektedir. DiscreteDoubleKeyFrame
elementleri KeyTime niteliğinde belirtilen anda, animasyon
uygulanan kontrolün ilgili özelliğinin value niteliği ile
belirtilen değerde olmasını sağlamaktadır. Söz gelimi animasyondaki
zaman çizelgesinin 2nci saniyesinde Top değeri 30 piksel, 1.5nci
saniyesinde Left değeri 150 piksel olacak şekilde
belirlenmektedir. Daha öncede belirtildiği gibi kontrolün söz konusu
koordinat noktalarına ulaşması sırasında akıcı bir efekt yerine
sıçrama(Jump) efekti uygulanmaktadır. Her halde bir yerden bir yere
ışınlanmanın WPF' cesinin bu olduğunu söyleyebiliriz. Bu durumu
aşağıdaki Flash görselinden daha net bir şekilde analiz edebiliriz.
Elbetteki aynı örneği kod yardımıylada
gerçekleştirebiliriz. Bunun için aşağıdaki XAML içeriğine ve kodlara
sahip bir pencere hazırlamamız yeterli olacaktır.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaDiscreteKullanimi"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kod ile Discrete Kullanimi" Height="300" Width="300">
<Canvas>
<Rectangle
Name="Dortgen"
Canvas.Top="0" Canvas.Left="0" Height="75" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
</Rectangle>
</Canvas>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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;
// Animasyon tiplerini içeren isim alanıdır
namespace AnimasyonIslemleri
{
public partial class KodlaDiscreteKullanimi : Window
{
private void AnimasyonuHazirla()
{
// Storyboard
nesnesi örneklenir
Storyboard strBrd
= new Storyboard();
//
Animasyonun sürekli tekrar edeceği belirtilir
strBrd.
RepeatBehavior
= RepeatBehavior.Forever;
//
Animasyonun zaman çizgisini tamamladığında aynı yoldan geriye
dönmesi sağlanır
strBrd.
AutoReverse
= true;
// Dortgen
nesnesinde Canvas' ın Top özelliği üzerinde Frame bazlı
animasyon yapılmasını sağlayacak şekilde
DoubleAnimationUsingKeyFrames nesnesi örneklenir
DoubleAnimationUsingKeyFrames dblA1 = new
DoubleAnimationUsingKeyFrames();
Storyboard.SetTargetName(dblA1, "Dortgen");
Storyboard.SetTargetProperty(dblA1, new
PropertyPath(Canvas.TopProperty));
// Frame'
lerdeki Top özelliğinin değerleri belirtilir. Bunun için
DiscreteDoubleKeyFrame nesneleri örneklenerek KeyFrames
koleksiyonuna eklenir.
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(150,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 1))));
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(30,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 2))));
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(120,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 3))));
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(60,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 4))));
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(90,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 5))));
dblA1.KeyFrames.Add(new DiscreteDoubleKeyFrame(75,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 6))));
//
DoubleAnimationUsingKeyFrames nesne örneği Storyboard' a alt
element olarak eklenir.
strBrd.
Children.Add(dblA1);
DoubleAnimationUsingKeyFrames dblA2 = new
DoubleAnimationUsingKeyFrames();
Storyboard.SetTargetName(dblA2, "Dortgen");
Storyboard.SetTargetProperty(dblA2, new
PropertyPath(Canvas.LeftProperty));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(150,
KeyTime.FromTimeSpan(new TimeSpan(0,0, 0, 1,500))));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(30,
KeyTime.FromTimeSpan(new TimeSpan(0, 0,0, 2,500))));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(120,
KeyTime.FromTimeSpan(new TimeSpan(0, 0,0, 3,500))));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(60,
KeyTime.FromTimeSpan(new TimeSpan(0, 0,0, 4,500))));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(90,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0,5,500))));
dblA2.KeyFrames.Add(new DiscreteDoubleKeyFrame(75,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0,6,500))));
strBrd.
Children.Add(dblA2);
// Pencere
yüklendikten sonra
Loaded += delegate(object
sender, RoutedEventArgs e)
{
// Animasyon başlatılır
strBrd.Begin(this);
};
}
public KodlaDiscreteKullanimi()
{
InitializeComponent();
AnimasyonuHazirla();
}
}
}
Frame tabanlı animasyon işlemlerinde
LinearDoubleKeyFrame ve DiscreteDoubleKeyFrame tipleri
dışında kullanılabilen bir diğer sınıfta SplineDoubleKeyFrame'
dir. Bu tip sayesinde, animasyon işlemi sırasındaki ileri ve geri yönlü
hareketlerde, hızlanma ve yavaşlama oranları daha net bir şekilde
belirlenebilir. Söz konusu hızlanma verilerini belirlemek için, sadece
0.0 ile 1.0 arasında değerler alabilen KeySpline
özelliğinden yararlanılır. Aşağıdaki XAML içeriğine sahip örnekte
SplienDoubleKeyFrame tipi kullanılmaktadır.

XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.SplineKullanimi"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Spline Kullanimi" Height="422" Width="181">
<Canvas>
<Rectangle Name="Dortgen"
Canvas.Top="0" Canvas.Left="0" Height="75" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Top)">
<SplineDoubleKeyFrame
KeyTime="0:0:3" Value="200" KeySpline="0.3,0.0 0.9,0.3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Window>
Bu örneğin çalışma zamanındaki çıktısı
aşağıdaki Flash animasyonunda olduğu gibidir.(Flash
dosyasının boyutu 298 Kb olduğundan yüklenmesi zaman alabilir.)
Dikkat edilecek olursa düşey düzlemde
hareket eden resim 3 saniyelik zaman dilimi içerisinde pencerenin üst
noktasından 200 piksel aşağıya gelmektedir. Ancak bu hareketi sırasında
KeySpline niteliğinde belirtilen değerler nedeni ile düşey olarak
hızlanarak ve ters yönde de yavaşlayarak ilerlemektedir. KeySpline
niteliğindeki değerler ile oynayarak daha farklı etkiler de elde
edilebilir. Hatta bu değerler ile oynayarak farklı etkilerin nasıl
oluşturulabileceğini incelemenizi şiddetle tavsiye ederim. Aynı örnek
kod yardımıylada aşağıdaki gibi geliştirilebilir.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaSplineKullanimi"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kod ile Spline Kullanimi" Height="397" Width="181">
<Canvas>
<Rectangle
Name="Dortgen"
Canvas.Top="0"
Canvas.Left="0" Height="75" Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg"/>
</Rectangle.Fill>
</Rectangle>
</Canvas>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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;
// Animasyon tiplerini içeren isim alanıdır
namespace AnimasyonIslemleri
{
public partial class KodlaSplineKullanimi : Window
{
private void AnimasyonuHazirla()
{
// Storyboard
nesnesi örneklenir, animasyonun tekrarlı ve geriye dönüşlü
olacak şekilde çalışacağı belirlenir
Storyboard strBrd
= new Storyboard();
strBrd
.RepeatBehavior
= RepeatBehavior.Forever;
strBrd
.AutoReverse
= true;
DoubleAnimationUsingKeyFrames dblA = new
DoubleAnimationUsingKeyFrames();
//
SplineDoubleKeyFrame nesnesi eklenir. Üçüncü parametre ile
hızlanma ve yavaşlama değerleri belirlenir.
dblA.KeyFrames.Add(new SplineDoubleKeyFrame(200,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 3)), new KeySpline(0.3,
0, 0.9, 0.3)));
//
Animasyonun Dortgen isimli nesneye ve içinde bulunduğu Canvas'
ın Top özelliğine uygulanacağı belirlenir
Storyboard.SetTargetName(dblA, "Dortgen");
Storyboard.SetTargetProperty(dblA,
new PropertyPath(Canvas.TopProperty));
// Animasyon
nesnesi Storyboard' a alt element olarak eklenir
strBrd.
Children.Add(dblA);
// Pencerenin
yüklenmesi tamamlandıktan sonra
Loaded
+= delegate(object sender, RoutedEventArgs e)
{
// Animasyon başlatılır
strBrd.
Begin(this);
};
}
public KodlaSplineKullanimi()
{
InitializeComponent();
AnimasyonuHazirla();
}
}
}
Bu örneklerdende anlaşılacağı üzere
farklı veri tipleri için yazılmış olan Frame bazlı animasyon tipleri
olduğunu söyleyebiliriz. Geliştirilen örnekler double tipi ile çalışan
özellikler üzerinde Frame bazlı animasyonlar geliştirilebilmesi için
DoubleAnimationUsingKeyFrames tipini kullanmaktadır. Ancak bu tip
dışında ColorAnimationUsingKeyFrames,
PointAnimationUsingKeyFrames, ByteAnimationUsingKeyFrames
vb... sınıflarda yer almaktadır. Tüm bu Frame bazlı animasyon tipleri
LinearTipAdıKeyFrame, DiscreteTipAdıKeyFrame ve
SplineTipAdıKeyFrame sınıflarına ait nesne örnekleri ile
çalışabilmektedir. Tabiki bu durum her veri türü için geçerli değildir.
Söz gelimi StringAnimationKeyFrames tipi sadece
DiscreteStringKeyFrame sınıfına ait nesne örneklerini taşıyabilir.
Dolayısıyla enterpoasyon(Interpolation) efektleri
gerçekleştirilemez.
Sıradaki örnekte bir Button kontrolünün
Text özelliğinin içeriğini Frame bazlı animasyon işleminde nasıl ele
alabileceğimizi inceleyeceğiz. Bu amaçla XAML içeriği aşağıdaki gibi
olan bir pencere tasarladığımızı düşünelim.

XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.StringKeyFrameAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StringKeyFrameAnimasyon" Height="149" Width="278">
<Grid>
<Button
Name="btnMerhaba"
Width="140"
Height="40" FontSize="12" FontWeight="Bold">
<Button.Triggers>
<EventTrigger
RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard
RepeatBehavior="Forever">
<StringAnimationUsingKeyFrames
Storyboard.TargetName="btnMerhaba"
Storyboard.TargetProperty="Content" Duration="0:0:6">
<!-- Eğer Duration süresi belirtilmesse DiscreteStringKeyFrame
elementlerinden sonuncusu gösterilmiyor. Sonuncusununda
gösterilmesi için Duration süresi son DiscreteStringKeyFrame'
inkinden fazla verilmelidir.-->
<DiscreteStringKeyFrame Value="WPF" KeyTime="0:0:1"/>
<DiscreteStringKeyFrame Value="ile" KeyTime="0:0:2"/>
<DiscreteStringKeyFrame Value="Temel" KeyTime="0:0:3"/>
<DiscreteStringKeyFrame Value="Animasyon" KeyTime="0:0:4"/>
<DiscreteStringKeyFrame Value="İşlemleri" KeyTime="0:0:5"/>
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</Window>
Bu örneğin çalışma zamanındaki işleyişi
aşağıdaki Flash görselinde olduğu gibidir. DiscreteStringKeyFrame
elementlerine ait Value nitelikleri tahmin edileceği üzere,
animasyonun bağlandığı kontrolün ilgili özelliğindeki string bilginin t
anında ne olacağını belirtmekte kullanılmaktadır. KeyTime
niteliğine verilen değerler ile söz konusu t anları belirtilir.
Elbetteki bu örnekteki animasyon etkisi
kod yardımıylada geliştirilebilir. Aşağıdaki kod parçalarında bu duruma
bir örnek verilmektedir.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.KodlaStringKeyFrameAnimasyon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="KodlaStringKeyFrameAnimasyon" Height="144" Width="300">
<Grid>
<Button
Name="btnMerhaba"
Width="140" Height="40" FontSize="12" FontWeight="Bold"/>
</Grid>
</Window>
Kod içeriği;
using System;
using System.Collections.Generic;
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 AnimasyonIslemleri
{
public partial class KodlaStringKeyFrameAnimasyon : Window
{
string slogan = "CSharp az keyword
ile çok iş yapmamızı sağlayan bir dildir";
private void AnimasyonuHazirla()
{
Storyboard
strBrd = new Storyboard();
strBrd
.RepeatBehavior
= RepeatBehavior.Forever;
StringAnimationUsingKeyFrames strA = new
StringAnimationUsingKeyFrames();
string[]
kelimeler = slogan.Split(' ');
strBrd.
Duration
= TimeSpan.FromSeconds(kelimeler.Length + 1);
for(int
i=1;i<=kelimeler.Length;i++)
{
strA.KeyFrames.Add(new
DiscreteStringKeyFrame(kelimeler[i-1],KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i))));
}
Storyboard.SetTargetName(strA, "btnMerhaba");
Storyboard.SetTargetProperty(strA, new
PropertyPath(Button.ContentProperty));
strBrd.
Children.Add(strA);
btnMerhaba.
MouseEnter
+= delegate(object sender, MouseEventArgs e)
{
strBrd.
Begin(this);
};
}
public KodlaStringKeyFrameAnimasyon()
{
InitializeComponent();
AnimasyonuHazirla();
}
}
}
Bu kez, bir slogan cümle içerisindeki
kelimeler boşluk karakterine göre Split metodu ile
ayrıştırılmakta ve elde edilen string dizisindeki her bir kelime için
DiscreteStringKeyFrame temelli, saniyede bir artan animasyon
uygulanmaktadır. Bu örnek kod parçasının çalışma zamanındaki çıktısı ise
aşağıdaki Flash görselindeki gibi olacaktır.
Makalemizde son olarak bir bileşenin
belirli bir rota üzerinde hareket etmesinin animasyon teknikleri ile
nasıl gerçekleştirilebileceğini incelemeye çalışacağız. Önceki
makalelerimizden hatırlayacağınız gibi, Path ve PathGeometry
tiplerini kullanarak birbirlerine bağlı yayların çizilmesi mümkündür. Bu
tip bir elementin oluşturacağı rotayı takip eden bir bileşen söz konusu
olduğunda, animasyon tiplerinden TipAdıAnimationUsingPath
isimlendirmesi ile tanımlananlardan yararlanbiliriz. Örneğin bir
PathGeometry ile tanımlanan rotada hareket edecek bir nesnenin
içinde bulunduğu Canvas' ın Top ve Left özellikleri
söz konusu ise DoubleAnimationUsingPath tipini kullanabiliriz.
Aşağıdaki XAML çıktısında bu durum örneklenmeye çalışılmaktadır.
XAML içeriği;
<Window
x:Class="AnimasyonIslemleri.PathFrameKullanimi"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PathFrameKullanimi" Height="300" Width="300">
<Window.Resources>
<PathGeometry
x:Key="YolGeometrisi">
<PathFigure>
<BezierSegment
Point1="0,0" Point2="10,120" Point3="70,40"/>
<ArcSegment
Point="150,125" SweepDirection="Clockwise" Size="50,50"
IsLargeArc="True" RotationAngle="60"/>
<ArcSegment
Point="200,200" SweepDirection="Counterclockwise" Size="50,50"
IsLargeArc="True" RotationAngle="60"/>
</PathFigure>
</PathGeometry>
</Window.Resources>
<Canvas>
<Path
Data="{StaticResource YolGeometrisi}"
Stroke="LightGray"
StrokeThickness="2"/>
<Rectangle
Height="65"
Name="Dortgen"
Width="55">
<Rectangle.Fill>
<ImageBrush ImageSource="Kitap.jpg" />
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger
RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimationUsingPath Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource YolGeometrisi}" Source="Y"
Duration="0:0:6" />
<DoubleAnimationUsingPath Storyboard.TargetName="Dortgen"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource YolGeometrisi}" Source="X"
Duration="0:0:6" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Window>
Söz konusu örnekte, Storyboard
elementi içerisinde DoubleAnimationUsingPath alt elementi
kullanılmaktadır. Bu elementlerden iki adet tanımlanmasının sebebi,
Dortgen isimli nesnenin Top ve Left özelliklerinin ayrı ayrı
değiştirilmesi gerekliliğidir. DoubleAnimationUsingPath tipinde yer alan
niteliklerden Storyboard.TargetName ile animasyonun hangi
kontrole uygulanacağı belirtilir ki bu örnekte söz konusu kontrol
Dortgen isimli Rectangle dır. Storyboard.TargetProperty
nitelikleri ise Rectangle' ın içerisinde bulunduğu Canvas'
ın Top ve Left özelliklerinin değerleri üzerinde
hareketlendirmeler yapılacağını belirtir. PathGeometry
nitelikleri tahmin edileceği üzere rota bilgisini içeren pencere
kaynağını (Windows Resource) işaret etmektedir. MSDN kaynakları
Resource olarak yapılan bu tip tanımlamaların animasyon
işlemlerinde performans yönünden olumlu katkı yapacağını belirtmektedir.
Static kaynak olarak tanımlanan YolGeometrisi isimli veri kümesi
yardımıyla Path elementinin rota bilgiside verilmektedir. Bunun içinde
Path elementinin Data niteliğine değer ataması
yapılmıştır. Bu örneğin çalışma zamanındaki çıktısı aşağıdaki Flash
animasyonunda olduğu gibidir. (Flash
dosyasının boyutu 352 kb olduğundan yüklenmesi zaman alabilir.)
Görüldüğü gibi WPF mimarisinde gerek
XAML tarafında gerekse kod tarafında animasyon işlemleri için son derece
etkili yollar kullanılabilmektedir. Bence burada önemli olan noktalardan
biriside işaretleme dili içerisinde bu tip gelişmiş fonksiyonelliklerin
geliştirilebilmesidir. İlerleyen makalelerimizde WPF ile ilgili farklı
konularada değinmeye çalışacağız. Böylece geldik bir makalemizin daha
sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler
dilerim.
Örnek Uygulama için Tıklayın