WPF2008/08/26 03:53

안녕하세요. 정말 오랜만의 포스팅입니다. 계속 바쁘다 핑계를 대고 있지만 사실은.. 게을러서 자꾸 포스팅이 늦어지고 있네요.. 죄송합니다 ㅜ_ㅜㅋ

이번 시간에는 실제 실무에서도 접할 수 있을 법한 내용이므로 한번쯤 따라 해보시는 것을 권장합니다.

예제에서는 아래 그림과 같이 화면 중앙에 빨간색 사각형을 마우스를 클릭했을 때 색이 노란색으로 바뀌고, Animation이 완료된 후 파란색으로 바뀌는 효과를 구현해보겠습니다.

사용자 삽입 이미지


<Window x:Class="WPFKorea.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WPF Korea - whatisthat.co.kr" Height="300" Width="300">


<Rectangle Width="150" Height="150">


<Rectangle.Fill>

<SolidColorBrush x:Name="BackgroundBrush" Color="Red" />

</Rectangle.Fill>


<Rectangle.Triggers>

<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">

<BeginStoryboard>

<Storyboard>

<ColorAnimation Storyboard.TargetName="BackgroundBrush"

Storyboard.TargetProperty="Color"

From="Red" To="Yellow"

Completed="ColorAnimation_Completed"/>

</Storyboard>

</BeginStoryboard>

</EventTrigger>

</Rectangle.Triggers>

</Rectangle>


</Window>

private void ColorAnimation_Completed(object sender, EventArgs e)

{

BackgroundBrush.Color = Colors.Blue;

}

실행 결과를 한번 볼까요? 그냥 보기에는 문제가 없는 코드처럼 보입니다. 하지만, 코드를 실행 해보면 아래 동영상처럼 클릭할 때 마다 빨강에서 노랑으로 변할 뿐 파랑으로 변하지는 않습니다. 마치 Completed 부분의 Code가 아무런 작업도 하지 않는 것처럼 보이는데, 이유는 Animation이 원래 속성의 기본값을 재정의 하기 때문입니다. 간단하게 설명하면 BackgroundBrush.Color 의 기본 공간이 Animation에서 사용하는 공간과 다르다고 생각 하시면 됩니다. 위 예제에서 실제 Color속성의 공간에는 파란색이 저장되지만, 화면에 보여질 때 사용하는 Color속성은 Animation에서 사용하는 공간을 참조하기 때문입니다. Animation이 시작되면 그 즉시 해당 속성에 대한 참조 위치가 변경 되기 때문에 Animation이 끝난 뒤에 속성을 변경하려고 해도 적용되지 않는 것처럼 보이는 것인데요. 원래의 속성이 기준 값이 되도록 하려면 Animation이 속성에 영향을 주지 않도록 구현 해야 합니다.

WPF에서는 아래와 같이 Animation이 속성에 영향을 주지 않도록 하는 3가지 방법을 제공 하고 있으며, 하나하나 살펴보도록 하겠습니다.

  • Animation의 FillBehavior속성을 Stop으로 설정한다.
  • Storyboard에서 Target객체를 제거.
  • 개별 Animation속성을 제거한다.

[Animation의 FillBehavior속성을 Stop으로 설정]

<ColorAnimation Storyboard.TargetName="BackgroundBrush"

Storyboard.TargetProperty="Color"

From="Red" To="Yellow"

FillBehavior="Stop"

Completed="ColorAnimation_Completed"/>

FillBehavior속성이 Stop이 되면 Animation이 완료된 시점부터는 대상 속성에 영향을 주지 않기 때문에, 코드가 정상적으로 작동하는 것을 확인 할 수 있습니다. FillBehavior를 사용하는 방법은 Animation이 완료된 시점에서만 사용 할 수 있습니다.

[Storyboard에서 Target객체를 제거]

<Window x:Class="WPFKorea.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WPF Korea - whatisthat.co.kr" Height="300" Width="300">


<Rectangle Width="150" Height="150" x:Name="Rectangle">


<Rectangle.Fill>

<SolidColorBrush x:Name="BackgroundBrush" Color="Red" />

</Rectangle.Fill>


<Rectangle.Triggers>

<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">

<BeginStoryboard>

<Storyboard x:Name="Storyboard">

<ColorAnimation Storyboard.TargetName="BackgroundBrush"

Storyboard.TargetProperty="Color"

From="Red" To="Yellow"

FillBehavior="Stop"

Completed="ColorAnimation_Completed"/>

</Storyboard>

</BeginStoryboard>

</EventTrigger>

</Rectangle.Triggers>

</Rectangle>


</Window>

private void ColorAnimation_Completed(object sender, EventArgs e)

{

Storyboard.Remove(Rectangle);

BackgroundBrush.Color = Colors.Blue;

}

Sotryboard에서 Target객체를 제거하는 방법은 Animation완료 시가 아니더라도 언제라도 사용할 수 있습니다.

[개별 Animation속성을 제거 ]

<Window x:Class="WPFKorea.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WPF Korea - whatisthat.co.kr" Height="300" Width="300">


<Rectangle Width="150" Height="150" x:Name="Rectangle">


<Rectangle.Fill>

<SolidColorBrush x:Name="BackgroundBrush" Color="Red" />

</Rectangle.Fill>


<Rectangle.Triggers>

<EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">

<BeginStoryboard>

<Storyboard x:Name="Storyboard">

<ColorAnimation Storyboard.TargetName="BackgroundBrush"

Storyboard.TargetProperty="Color"

From="Red" To="Yellow"

FillBehavior="Stop"

Completed="ColorAnimation_Completed"/>

</Storyboard>

</BeginStoryboard>

</EventTrigger>

</Rectangle.Triggers>

</Rectangle>


</Window>

private void ColorAnimation_Completed(object sender, EventArgs e)

{

Rectangle.BeginAnimation(SolidColorBrush.ColorProperty, null);

BackgroundBrush.Color = Colors.Blue;

}

이 방법은 BeginAnimation 메서드를 사용하여 속성과 연결된 Animation을 Null로 할당하여 Animation과 Property간의 연결을 중단하는 방법입니다.

위 3가지 예제의 결과는 모두 같은 결과를 나타내며 결과는 아래와 같습니다.



사용자 삽입 이미지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 곡스
WPF2008/08/07 00:55


이번 시간에는 위 동영상과 같이 마우스가 움직일 때 마다 원이 나타나는 효과를 구현해 보았습니다. (동영상을 올릴때 압축이 되서 그런지 약간 지저분해 보이기도 하네요ㅎㅎ) 소스코드는 아래와 같습니다.

[XAML]

<Window x:Class="WPFClock.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>
<Style TargetType="Ellipse">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
</Style>
<Storyboard x:Key="EllipseStoryBoard">
<DoubleAnimation To="8"
toryboard.TargetProperty
="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"/>
<DoubleAnimation To="8"
toryboard.TargetProperty
="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"/>
<DoubleAnimation To="0" Storyboard.TargetProperty="(UIElement.Opacity)"/>
</Storyboard>
</Window.Resources>
<Canvas x:Name="Root"/>
</
Window>

[C#]

public partial class Window1 : Window
{

public Window1()
{
InitializeComponent();
this.MouseMove += new MouseEventHandler(Window1_MouseMove);
}

void Window1_MouseMove(object sender, MouseEventArgs e)
{
Point Pt = e.GetPosition(this);
Add(Pt.X, Pt.Y);
}

//
마지막으로 객체가 생성된 시간
TimeSpan LastAdd;
public void Add(double X, double Y)
{

if ((DateTime.Now.TimeOfDay - LastAdd).Milliseconds < 50) return;
LastAdd = DateTime.Now.TimeOfDay;

Ellipse Ellipse = new Ellipse();
Ellipse.Stroke = GetRandomColorBrush();

int Size = (Byte)Rnadom.Next(5, 15);
Ellipse.Width = Ellipse.Height = Size;
Ellipse.Name = "_" + Ellipse.GetHashCode().ToString();

Canvas.SetLeft(Ellipse, X - Size / 2);
Canvas.SetTop(Ellipse, Y - Size / 2);

Root.RegisterName(Ellipse.Name, Ellipse);
Root.Children.Add(Ellipse);

Storyboard EllipseStoryboard = (Resources["EllipseStoryBoard"] as Storyboard).Clone();
Storyboard.SetTargetName(EllipseStoryboard, Ellipse.Name);

EllipseStoryboard.Completed += new EventHandler(EllipseStoryboard_Completed);
Ellipse.BeginStoryboard(EllipseStoryboard);

}

SolidColorBrush GetRandomColorBrush()
{
Random Rnadom = new Random(DateTime.Now.Millisecond);
Color StrokeColor = Color.FromArgb(
(Byte)Rnadom.Next(80, 255),
(Byte)Rnadom.Next(0, 255),
(Byte)Rnadom.Next(0, 255),
(Byte)Rnadom.Next(0, 255)
);
return new SolidColorBrush(StrokeColor);

}

void EllipseStoryboard_Completed(object sender, EventArgs e)
{

Storyboard Storyboard = (sender as ClockGroup).Timeline as Storyboard;
Ellipse Ellipse = FindName(Storyboard.GetTargetName(Storyboard)) as Ellipse;

Root.UnregisterName(Ellipse.Name);
Root.Children.Remove(Ellipse);

}
}

코드가 꾀 길어 보이지만 실제로는 복잡한 내용은 없으니 한줄 한줄 천천히 살펴보시면 이해 하실 수 있을 것입니다. (혹시 이해가 잘 안 되는 부분이나 추가 설명이 필요한 부분은 댓글 달아주시면 설명 해드리도록 하겠습니다.)

사용자 삽입 이미지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 곡스
WPF2008/08/04 12:08

정말 오래간만에 포스팅 입니다. 프로젝트 마감 때문에 블로그에 신경을 못쓴거 죄송합니다 ㅠ_ㅜ 이번 시간에는 네이트온이나 MSN등에서 친구가 접속하면 화면 하단에 나타나는 Animation Window를 간단하게 구현해보도록 하겠습니다.



아래는 XAML 코드입니다.

<Window x:Class="AnimationWindwo.Window1"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="Window1" Height="120" Width="165" WindowStyle="None" ResizeMode="NoResize" >
<Window.Resources>
<ImageBrush ImageSource="Window.jpg" x:Key="Background"/>
<Storyboard x:Key="Animation">
<DoubleAnimation By="-150" Duration="0:0:0.5" Storyboard.TargetProperty="Top"/>
<DoubleAnimation BeginTime="0:0:2.5" Duration="0:0:0.5" By="150" Storyboard.TargetProperty="Top"/>
</Storyboard>

</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard Storyboard="{StaticResource Animation}"/>
</EventTrigger>
</Window.Triggers>
<Grid Background="{StaticResource Background}"/>
</
Window>

위 소스코드에서는 노란색으로 칠해진 부분이 중요한 부분인데요, 각각 설명을 해드리겠습니다.

WindowStyle="None"

WindowStyle은 위 그림과 같이 Window의 테두리를 없애는 부분입니다.

ResizeMode="NoResize"

그리고 WindowStyle만 None으로 할 경우 크기를 조절할 수 있는 테두리가 아래 그림과 같이 생기게 되는데 이 부분을 없애기 위해 ResizeMode를 NoResize로 설정합니다.

그리고 실제 Animation고 관련된 부분입니다.

<Storyboard x:Key="Animation">
<DoubleAnimation By="-150" Duration="0:0:0.5" Storyboard.TargetProperty="Top"/>
<DoubleAnimation BeginTime="0:0:2.5" Duration="0:0:0.5" By="150" Storyboard.TargetProperty="Top"/>
</
Storyboard>

DoubleAnimation을 사용해서 Top Property를 -150만큼 0.5초 동안 감소 시키고 2.5초 뒤에 다시 150만큼 증가 시킵니다. By Property를 사용했기 때문에 Window가 생성된 위치에서 위쪽으로 이동했다가 2초 뒤 아래로 이동하게 됩니다. 우리가 구현하고자 하는 Window는 회면 오른쪽하단에서 움직임이 발생해야 함으로 화면 해상도에 맞춰 창의 시작 위치를 고정 시켜 줘야 하는데요, 이 부분은 아래와 같이 간단한 C# Code를 조금 추가하여 해결 할 수 있습니다.

void Window1_Loaded(object sender, RoutedEventArgs e)
{
this.Left = System.Windows.SystemParameters.PrimaryScreenWidth - this.Width;
this.Top = System.Windows.SystemParameters.PrimaryScreenHeight;
}

Window객체가 Load되었을 때 SystemParameters Class에서 제공하는 화면의 크기를 사용해 Window의 위치를 조정합니다.

<EventTrigger RoutedEvent="Window.Loaded">
<
BeginStoryboard Storyboard="{StaticResource Animation}"/>
</
EventTrigger>

마지막으로 Event Trigger를 사용해 Window.Loaded 이벤트가 발생하면 위에서 구현한 StoryBoard를 시작하면됩니다.
사용자 삽입 이미지

 
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 곡스
Silverlight2008/08/02 08:45

SFC 2번째 포스팅입니다. 이번 시간에는 Silverlight의 Code 레벨에서 Animation을 보다 쉽게 사용 할 수 있도록 돕기 위해서 Animation Engine을 구현해보았습니다. 한참 진행중인 부분이라 아직 완성도 면에서는 떨어지지만, 보다 다양한 Effect를 연출할 수 있는 Engine으로 개선할 예정입니다. 아래 영상은 현재 SFC Animation Engine에서 제공하는 기본적인 기능입니다.



현재 Opcity , Rotate, Scale, Skew Animation을 제공하며 여러가지 Animation을 조합하여 사용 할 수 있는 Animator를 제공합니다.

사용방법은 아래와 같이 Animation객체를 생성하고 Animator에 추가 한뒤 Begin 메서드를 사용해 애니메이션을 시작합니다. 그리고 Aniamtion객체를 생성할때 Target이 되는 Object를 생성자 Parameter로 전달하므로 유의하시기 바랍니다.

SFCScaleAnimation ScaleAnimation = new SFCScaleAnimation(Source);
SFCOpacityAnimation OpacityAnimation = new SFCOpacityAnimation(Source);
ScaleAnimation.ScaleXTo = 8;
ScaleAnimation.ScaleYTo = 8;
OpacityAnimation.To = 0;
SFCAnimaitor Animaitor = new SFCAnimaitor();
Animaitor.Animations.Add(ScaleAnimation);
Animaitor.Animations.Add(OpacityAnimation);
Animaitor.Duration = TimeSpan.FromMilliseconds(1000);
Animaitor.FillBehavior = FillBehavior.Stop;
Animaitor.Begin();

아래 SFC전체 소스코드와 예제 코드를 첨부합니다~ ^_^
좋은 하루되세요~


사용자 삽입 이미지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 곡스