Tag Archives: animation

Creating a Game in Blazor – Part 3 – Graphics

In this post I started writing a game in Blazor. In this last post, I covered how we could use the keyboard to move an object around, and how we could apply gravity.

In this post, we’re going to refactor, and we’re going to replace the word test with something approximating Willy.

Refactor

Just because we’re writing a game in Blazor is no reason not to use the IoC container in order to better structure the code. I’m not going to cover all of the refactoring here; however, the changes are here.

We’ve added a sub-directory called GameLogic which contains all the relevant classes:

At some point in the future, we may separate this directory into its own project; but for now, we have four classes:

Controls – this handles the user input.

Graphics – this will handle the manipulation of the graphics.

Player – this handles behaviour of the player.

World – this deals with the things such as collisions, gravity, etc.

WorldSettings – these are just a list of variables that control how things move. In the original game, there was a POKE that meant you could jump so high that you went into the next room.

I won’t cover what’s actually in these classes – it’s essentially what was in the main Razor file. I will cover the change to the razor file itself:

@page "/"
@using System.Timers
@using BlazorGame.GameLogic
@inject IPlayer Player
@inject IControls Controls
@inject IWorld World

<div @onkeydown="HandleKeyDown" @onkeyup="HandleKeyUp" @onkeydown:preventDefault 
    style="background-color: #000000; width: 80vw; height: 80vh; margin: auto"
    tabindex="0" @ref="mainDiv">
    <div style="color: white; top: @(Player.Top)px; left: @(Player.Left)px; width: 20px; position: relative">test</div>
</div>

@code {

    private ElementReference mainDiv;    
    private Timer _timer;

    private void HandleKeyUp(KeyboardEventArgs e) =>
        Controls.KeyUp(e.Code);    

    private void HandleKeyDown(KeyboardEventArgs e) =>    
        Controls.KeyDown(e.Code);    

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await mainDiv.FocusAsync();
        }
    }

    protected override Task OnInitializedAsync()
    {
        _timer = new Timer();
        _timer.Interval = 16;
        _timer.Elapsed += TimerElapsed;
        _timer.AutoReset = true;
        _timer.Enabled = true;        

        return base.OnInitializedAsync();
    }

    private void TimerElapsed(Object source, System.Timers.ElapsedEventArgs e)
    {
        Update();
        Draw();
    }

    private void Update()
    {
        World.ApplyPhysics();
    }

    private void Draw() => 
        this.StateHasChanged();    

}

This is much more terse than before, and delegates most of its functionality to the classes that we described above. You’ll see at the top that we @inject those classes into the page.

Finally, the classes are registered in Program.cs:

        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("#app");

            builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
            builder.Services.AddSingleton<IWorld, World>();
            builder.Services.AddSingleton<IPlayer, Player>();
            builder.Services.AddSingleton<IControls, Controls>();

            await builder.Build().RunAsync();
        }

This is by no means the last refactoring that we’ll do, but it’s perhaps the last one that will make it into its own section of a post.

Graphics

For the graphics, I spent a while trying to get various graphics libraries to work cross platform. I finally realised that, not only did I not need a graphics library, but that I’d solved this issue before – well, more or less. The answer was to use CSS to animate the image. The very first step was to add a sprite sheet; which I got from here, and since Jet Set Willy is the same character as manic miner (with just one pixel difference in the hat), I managed to add a sprite sheet:

The next change was to alter the HTML in Game.razor slightly:

<div @onkeydown="HandleKeyDown" @onkeyup="HandleKeyUp" @onkeydown:preventDefault 
    style="background-color: #000000; width: 80vw; height: 80vh; margin: auto"
    tabindex="0" @ref="mainDiv">
    <div style="color: white; top: @(Player.Top)px; left: @(Player.Left)px; width: 16px; height: 17px; overflow: hidden; position: relative">
        <img 
            src="/images/Willy-Sprite-Sheet.png" 
            style="margin: 0 @(Graphics.PlayerOffset)px; transform: scaleX(@(Graphics.PlayerDirection))" />
    </div>
</div>

There’s a few things to unpick here. Let’s start with the interaction between the div and the img. Essentially, we’re using the div as a window into the image; similar to this:

Both the margin and transform are set to bound properties of a new Graphics class, which we’ll come to in a second; but first, let’s see the other change to this file:

    private void Update()
    {
        World.ApplyPhysics();
        if (Player.IsWalking)
        {
            Graphics.CyclePlayer();
        }
    }

This allows us to change the bound variables that we mentioned earlier.

Now that we’ve seen the changes to the main razor file, let’s see the new Graphics class:

    public class Graphics : IGraphics
    {
        private readonly IPlayer _player;
        private int _playerOffset = 0;
        private DateTime _lastUpdate = DateTime.MinValue;

        public Graphics(IPlayer player)
        {
            _player = player;
        }

        public int PlayerOffset => _playerOffset;

        public int PlayerDirection =>
            _player switch
            {
                { IsWalkingLeft: true } => -1,
                { IsWalkingRight: true } => 1,
                _ => 0
            };
        
        public void CyclePlayer()
        {
            if (_lastUpdate.AddMilliseconds(100) > DateTime.Now) return;

            if (_playerOffset > -48)
                _playerOffset -= 16;
            else
                _playerOffset = 0;

            _lastUpdate = DateTime.Now;
        }
    }

This is essentially a utility, or helper class. It encapsulates details about the graphics that are displayed, and uses the Player class to do so. Most of it is relatively self-explanatory, with the possible exception of CyclePlayer which moves the offset that we mentioned earlier no more frequently that every 100ms.

That’s pretty much it; we now have a walking Willy:

What’s Next?

In the next post, we’ll try to add a platform, and some collision logic.

References

https://www.spriters-resource.com/fullview/113060/

https://gunnarpeipman.com/csharp-reading-embedded-files/

https://www.hanselman.com/blog/how-do-you-use-systemdrawing-in-net-core

https://www.davidguida.net/blazor-gamedev-part-11-improved-assets-loading/

https://stackoverflow.com/questions/493296/css-display-an-image-resized-and-cropped

CSS Animations Sprite Sheet

I’ve recently been investigating the prospect of creating a web-site, where an animation (admittedly a cheesy one) is played out when you load the page. My idea was that two sprites would walk to the centre of the screen. I was actually thinking to mimic something like Manic Miner. Initially, I thought I’d probably need to do some messing around with image manipulation in Javascript, but this gave me the idea that I might be able to run the entire thing through CSS.

Sprite Sheet

The first thing that you need to get is something to animate. The principle of a sprite sheet is that you have many images in a single image file. This is simply a speed trick – it’s faster to pull down a single image, and cache it, than to constantly load separate images for each part of the animation.

If you have separate images, then for this post to work for you, you’ll need to combine them into a single sprite sheet. The tool suggested in the video above is Sprite Sheet Packer. I’ve used this before, and it does the job – you can also do this manually (although you would have to be careful about the spacing).

Now that we have a sprite sheet, we can add it to our project; in my case, I’ve put it in wwwroot\assets.

Let’s talk about how we can layout our page, and animate it; we’ll start with the HTML.

HTML

The HTML here is the simplest part: we just want two divs:

<div id="testdiv"></div>
<div id="testdiv2"></div>

That’s all the HTML; everything else is CSS; let’s start with the animation.

CSS

Onto the CSS, which is the crux of the whole thing. Let’s start with the @keyframes. This is the part where you can actually define an animation. In our case, we’ll need three of them: one to move the sprite left, one to move it right, and one to animate it.

Move Left & Right

The animation to move an element on the screen is pretty straightforward, you just tell it where to start, and where to stop:

@keyframes moverightanimation {
    from { 
        left: 10%; 
    }
    to {
        left: calc(50% - 25px);
    }
}

@keyframes moveleftanimation {
    from {
        left: 90%;
    }
    to {
        left: calc(50% + 25px);
    }
}

As you can see, you can start (or stop) at an absolute position (10px for example), or a percentage, or a calculated value.

Animate

The animation is a bit strange; here’s the code:

@keyframes move {
    100% {
        background-position: -72px, 0px;
    }
}

What this is doing is setting the final position to be negative the width of the full sprite sheet (this will only work for horizontal sheets). We’ll then tell it to step through the images in the element itself. Here’s the CSS for one of the divs:

#testdiv {
    position: absolute;
    left: 20%;
    top: 300px;
    width: 24px;
    height: 30px;    
    animation: moverightanimation 4s forwards, move 1s steps(3) infinite;
    background: transparent url('../assets/spritesheet.png') 0 0 no-repeat;    
}

Here, we’re calling multiple animations (moverightanimation and move); for the move, we’re specifying a step – that is, we’re telling it that it needs to get from where it currently is, to 100% over 3 steps, and there are 3 sprites in my sprite sheet, so it will helpfully divide one by the other and come up with a value to increase by each time.

The opposite call does almost the same:

#testdiv2 {
    position: absolute;
    left: 80%;
    top: 300px;
    width: 24px;
    height: 30px;    
    animation: moveleftanimation 4s forwards, move 1s steps(3) infinite;
    background: transparent url('../assets/spritesheet2') 0 0 no-repeat;
}

Summary

As someone who spends as little time as they can messing with UI and CSS, I thought this was a fun little exercise.

Playing multiple videos simultaneously using HTML5

I was interested to see how playing multiple videos simultaneously affected the performance of a web page. This probably seems a little like a time machine back to 1995 – I’ll soon be posting about flashing red text and Dreamweaver!

However, playing short videos with only a few frames can be a way to draw attention to a particular part of the page; for example, if you’re browsing a clothing catalogue and one of the models moves when you hover over.

It’s worth pointing out that the entire page will be local, and so I have no network considerations whatsoever. This isn’t, however, about having three Netflix streams running at the same time – it’s short, and small videos.

The video that I’m using came from here. I’m creating an effect whereby you hover over an image of a space ship and it explodes.

MP4

It’s worth bearing in mind that most video formats are not supported by most browsers. MP4 is the exception, so it looks like this is the way to go for video encoding. I used this tool to convert the file.

HTML

Here’s the HTML for a single icon:

<head>
  <script src="HoverAnimate.js"></script>
</head>
<body onload="loaded()">
  <div id="ship1" style="background-image: url('assets/titan.png'); background-repeat: no-repeat; background-size: 50px 50px; width: 50px; height: 50px">
    <video  width="50" height="50" id="ship1-video" 
            style="visibility: hidden">
      <source src="assets/explosion.mp4" type="video/mp4" />
    </video>
  </div>
</body>

Clearly this could be neater if the CSS was separated, but essentially what we have is a div element with a scaled background image, which contains a video (currently hidden). The next thing is the Javascript that plays the video:

function loaded() {
    var imgs = document.getElementsByTagName("div");
    [].forEach.call(imgs, function (item) {
        if (item.style.backgroundImage !== "") {
            item.addEventListener('mouseover', hoverImg, false);
        }
    });
   
}

function hoverImg(e) {      
    var vid = document.getElementById(this.id + "-video");
    vid.onended = function() {        
        vid.style.visibility = 'hidden';
    }
        
    vid.style.visibility = 'visible';
    vid.play();
}

This iterates through all the div elements and, for those that has a background image, hooks up a hover event. I’ve also assumed that the div element will be named using the format “{imagename}-video”.

Conclusion

I tried this with seven videos simultaneously, and didn’t see any jerking of the animations. Whether this would stand up under networked conditions, it’s hard to say, but with the video locally available, performance is fine.

References

https://www.w3schools.com/html/html_media.asp

http://www.online-convert.com/

https://www.w3schools.com/html/html5_video.asp

http://www.dreamincode.net/forums/topic/281583-video-plays-on-mouse-over-but-not-with-multiple-videos/

https://stackoverflow.com/questions/10881678/html-play-a-video-inside-an-image

Create CSS effect to “Shine” a button border

Imagine that you have an HTML button or element on a page and you would like an effect where the border shines all around the perimeter. this provides an excellent example of an effect of the entire element shining, and this post will largely be based on that code.

Animations

CSS has the concept of an animation, to define it, use the following syntax:

.growOnHover:hover:after {
    animation: growAnimation 1s;
}

Here is the HTML referencing this:

<a href="#" class="growOnHover">Grow</a>

Tge “growAnimation” refers to a KeyFrame:

@keyframes growAnimation {
    from {width: 100px; height: 100px;}
    to {width: 110px; height: 110px;}
}

The effect

The effect that I want is for a light to run around the circumference of the button when it’s hovered over. In this case, instead of animating from .. to, we can specify at which stage a particular section of the animation kicks in.

.borderShine:after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 5;
  height: 5;
  opacity: 0;  

  border-radius: 1;

  background: rgba(255, 255, 255, 10);
}

.borderShine:hover:after {
  animation: shineAnimation 2s 1;  
}

@keyframes shineAnimation {
  0%   {left: 0; top: 0; width: 2; height: 2; opacity: 0}
  10%  {width: 100; height: 2}  
  20%  {left: 98; top: 0; width: 2; height: 2}
  25%  {opacity: 1;}
  30%  {height: 100}
  40%  {left: 98; top: 98; height: 2}
  50%  {left: 0; top: 98; width: 100}
  55%  {opacity: 1;}
  60%  {left: 0; top: 98; width: 2; height: 2}
  70%  {left: 0; top: 0; width: 2; height: 100}
  80%  {left: 0; top: 0; width: 2; height: 2}
  100% {opacity: 0;}
}

There are a few useful things to remember here:

  • The animation is a transition between the state that the screen is currently in, and the state that you want it to be in; so, for example, the opacity set to 1 at 25% will cause the white bar to gradually appear over the steps between the two. The reason that I’ve set opacity twice here is to prevent it from transitioning back too soon.
  • All the figures above are absolute (as my buttons are 100 x 100).

References

http://jsfiddle.net/AntonTrollback/nqQc7/

https://css-tricks.com/useful-nth-child-recipies/

https://css-tricks.com/using-multi-step-animations-transitions/

Rotate a Shape Around an Axis Using HTML5 and Javascript

Imagine, for a minute, that you want to rotate a red square around its centre… on a web page. Following on from my previous post about games using HTML5 / JS this post details how to do such a thing.

Context

Before drawing a rectangle, rotating it, or anything else, you need a context:

var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");

Now you have a context, you can do things like clear the canvas; for example:

ctx.clearRect(0, 0, windowWidth, windowHeight);

fillRect

In HTML5, you have three methods that will be of use, and the first, and probably most important, is fillRect. It is impossible to rotate a square around its centre without a square. The syntax for fillRect is probably as you would expect:

ctx.fillRect(x, y, width, height);

rotate

The syntax for rotation is this:

ctx.rotate(rotationDegree * Math.PI / 180);

Whilst I may, during my school years, have been able to explain the sum above – I just copied it from the internet. Given the number of places where is looks exactly alike, I would guess that I’m not the first person to do that.

Just using the three lines above will give you a rotating rectangle; however, the rotation axis will be 0, 0. It took me a while to understand exactly how this works, but the key is `translate`.

translate

To me, this function is completely counter-intuitive. What it does it to offset the centre of the context by the parameters given. If the initial centre is 0, 0 (which it is by default), the following line will make it 10, 10:

ctx.translate(10, 10);

The centre of the context is 10, 10; if I call it a second time:

ctx.translate(10, 10);

The centre of the context is now 20, 20! There are two ways to reset the offset – you can simply negate the offset (by calling it with negative values), or you can call ctx.save() before the change, and ctx.restore() afterwards.

Putting it all together

So, what does all this look like in a single coherent piece of code:

        var canvas = document.getElementById("mainCanvas");
        var ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, windowWidth, windowHeight);

        var halfWidth = (iconWidth / 2);
        var halfHeight = (iconHeight / 2);

        var centreX = x - halfWidth;
        var centreY = y - halfHeight;

        ctx.fillStyle = "#FF0000";
        ctx.translate(centreX, centreY);
        ctx.rotate(rotationDegree * Math.PI / 180);
        ctx.fillRect(-halfWidth, -halfHeight, iconWidth, iconHeight);

        ctx.translate(-centreX, -centreY);

The key part to note here is the call to fillRect. Because the translate has now set the centre to be the centre of the drawn image, the image needs to be positioned at -(image width / 2).

… and you, too can have a spinning red rectangle on your screen.

References

http://www.w3resource.com/html5-canvas/html5-canvas-translation-rotation-scaling.php

https://gist.github.com/geoffb/6392450

Playing a longer running animation in Unity

Continuing on with my list of things that I’ve found in unity (I’m using 5, but have no reason to believe these wouldn’t work for 4), I had cause to execute an attack animation in a character. For reference, the character I’ve been using is here

So far, when playing an animation, I’ve used something similar to this:

gameObject.GetComponent<Animation>().Play("Idle_2");

In fact, if you put that in the Update of the linked object, you’ll get an angry looking chap looking like he’s about to charge. In order to plumb in the attack, it’s necessary to cache the animation. Start with a class level variable:

private Animation _animation;

Then, inside the update statement, something similar to this:

void Update ()
{
    if (_animation != null && _animation.IsPlaying("Attack_1")) return;

    if (Input.GetKeyDown(KeyCode.Space))
    {
        if (_animation == null)
            _animation = gameObject.GetComponent<Animation>();
        _animation.Play("Attack_1");            
    }
}

One of the bizarre things that I learnt about unity while doing this, was that if you have a null reference, it doesn’t crash. It doesn’t work, but it doesn’t crash.

I find this annoying.

Animation in XAML (Part 5)

Introduction

In this post, I would like to specifically focus on the differences between animations in WPF and in WinRT. Some quick disclaimers: As far as I’m aware, Windows Phone and WinRT are interchangeable where animations are concerned, but I base that only on my efforts to move a specific animation between the two. Consequently I won’t look at Windows Phone.

The Animation

Here’s a sample of the animation to cause the button to spin and disappear from previous posts:

         private void SpinAndDisappear_Click( object sender, RoutedEventArgs e)
        {
           
            Button b = (Button)sender;
           
            DoubleAnimation da = new DoubleAnimation (b.Width, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.WidthProperty, da);

            DoubleAnimation da2 = new DoubleAnimation (b.Height, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.HeightProperty, da2);

            DoubleAnimation da3 = new DoubleAnimation (0, 360, TimeSpan.FromSeconds(.5));           
            RotateTransform transform = (RotateTransform )b.RenderTransform;
            transform.BeginAnimation( RotateTransform.AngleProperty, da3 );
        }

How it Works in WinRT

Okay, so the short answer is: it doesn’t – well, that doesn’t anyway! There are a few reasons why this won’t work in WinRT, but the most annoying one is that WinRT doesn’t support multiple animations on the same element. That is, only one storyboard can be running for a given element at any time.

Before we get into a workaround, so cunning, you could tie a tail to it and call it a fox, let’s look at the size animation in WinRT (as it’s not exactly the same); first the XAML:

             < Button x : Name="SpinAndDisappear" Content ="Don't press me" Click="SpinAndDisappear_Click"
                RenderTransformOrigin ="0.5, 0.5" Height ="100" Width="300"/>

And the code behind:

             UIElement obj = ( UIElement)SpinAndDisappear;

            obj.RenderTransform = new CompositeTransform ();

            var story = new Storyboard ();

            var xAnim = new DoubleAnimation ();
            var yAnim = new DoubleAnimation ();           

            xAnim.Duration = TimeSpan.FromSeconds(2);
            yAnim.Duration = TimeSpan.FromSeconds(2);           

            xAnim.To = 0;
            yAnim.To = 0;
           
            story.Children.Add(xAnim);
            story.Children.Add(yAnim);

            Storyboard .SetTarget(xAnim, obj);
            Storyboard .SetTarget(yAnim, obj);

            Storyboard .SetTargetProperty(xAnim, "(UIElement.RenderTransform).(CompositeTransform.ScaleX)" );
            Storyboard .SetTargetProperty(yAnim, "(UIElement.RenderTransform).(CompositeTransform.ScaleY)" );
                      
            story.Begin();

I’ve borrowed quite heavily here from this article by Iris Classon:

http://irisclasson.com/2012/06/28/creating-a-scaletransform-animation-in-c-for-winrt-metro-apps/

Okay, so I want to execute two animations at the same time; surely I just do this:

         void SpinAnimation()
        {
            UIElement obj = ( UIElement)SpindAndDisappear;

            obj.RenderTransform = new RotateTransform ();
            var storySpin = new Storyboard ();
            var spinAnim = new DoubleAnimation ();
            spinAnim.Duration = TimeSpan.FromSeconds(2);
            spinAnim.From = 0;
            spinAnim.To = 360;
            storySpin.Children.Add(spinAnim);
            Storyboard .SetTarget(spinAnim, obj);
            Storyboard .SetTargetProperty(spinAnim, "(UIElement.RenderTransform).(RotateTranform.Angle)" );
           
            storySpin.Begin();
        }

And call SpinAnimation after the first StoryBegin()? That did work in WPF. If you do this, what you get is a rotation animation only. As stated before, one element, one animation. The workaround is ingenious and, unfortunately, not my idea:

http://stackoverflow.com/questions/20224307/running-multiple-animations-in-windows-store-app

But here’s how it looks:

         < Frame x : Name="SpindAndDisappearParent" Height ="100" Width ="300"
               RenderTransformOrigin ="0.5, 0.5">
            < Button x : Name="SpinAndDisappear" Content ="Don't press me"Click="SpinAndDisappear_Click"
                RenderTransformOrigin ="0.5, 0.5" Height ="100" Width="300"/>

         </ Frame>

It’s important that the sizes of the parent and child elements are the same; next, just change the SpinAnimation() function like so:

         void SpinAnimation()
        {
            UIElement obj = ( UIElement)SpindAndDisappearParent;

            obj.RenderTransform = new RotateTransform ();
            var storySpin = new Storyboard ();
            var spinAnim = new DoubleAnimation ();
            spinAnim.Duration = TimeSpan.FromSeconds(2);
            spinAnim.From = 0;
            spinAnim.To = 360;
            storySpin.Children.Add(spinAnim);
            Storyboard .SetTarget(spinAnim, obj);
            Storyboard .SetTargetProperty(spinAnim, "(UIElement.RenderTransform).(RotateTranform.Angle)" );
           
            storySpin.Begin();
        } 

Conclusion

As you can see, I’ve rested heavily on the shoulders of giants here (which is another way of saying I’ve basically used other peoples code and ideas). Having said that, this area is virtually deserted as far as internet resources go; that’s why I started this series of articles in the first place.

Hopefully they’ve proved helpful.

Animation in XAML (Part 4)

Introduction

Following on from http://pmichaelsdev.wordpress.com/2013/11/18/animation-in-xaml-part-3/ this post is about achieving the simultaneous effect of spinning and disappearing. I thought I’d also use it to list a few other animations and how to achieve them. They’re all variations on a theme to be honest, but I’ll try to list as many as may be useful.

A word of note: most of the animations will be on buttons, but I’m not aware of any restrictions as to the target (it can be any UI Element). Also, the code listed is all based on a button event; again, this can be any event that makes sense… or even one that doesn’t. For example; try the spin and disappear on MouseOver!

Spin And Disappear

Code behind:

             Button b = (Button)SpinAndDisappear;
           
            DoubleAnimation da = new DoubleAnimation (b.Width, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.WidthProperty, da);

            DoubleAnimation da2 = new DoubleAnimation (b.Height, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.HeightProperty, da2);

            DoubleAnimation da3 = new DoubleAnimation (0, 360, TimeSpan.FromSeconds(.5));           
            RotateTransform transform = (RotateTransform )b.RenderTransform;
            transform.BeginAnimation( RotateTransform.AngleProperty, da3 );

XAML:

         <Button x:Name="SpinAndDisappear" ...
                RenderTransformOrigin="0.5, 0.5">           
           
            <Button.RenderTransform>
               
                 <RotateTransform>
               
                 </RotateTransform>
            </Button.RenderTransform>
               </Button>

Fade

Code behind:

             Button b = ( Button)Fade;

            DoubleAnimation da = new DoubleAnimation (b.Opacity, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation(Button.OpacityProperty, da);


Highlight The Current Textbox (Border Animation)

This is a nice little effect: when the user hovers the mouse over the textbox, the border is animated to make it stand out.

XAML:

             <TextBox Width ="300" Height="50" x:Name ="border" MouseEnter="border_MouseEnter"
                     MouseLeave="border_MouseLeave">
               
            </TextBox>

Code behind:

         private void border_MouseEnter( object sender, RoutedEventArgs e)
        {
            TextBox t = ( TextBox)border;
            ThicknessAnimation ta = new ThicknessAnimation (new Thickness (3), TimeSpan.FromSeconds(.3));
            t.BeginAnimation( TextBox.BorderThicknessProperty, ta);
        }

        private void border_MouseLeave( object sender, MouseEventArgs e)
        {
            TextBox t = ( TextBox)border;
            ThicknessAnimation ta = new ThicknessAnimation (new Thickness (1), TimeSpan.FromSeconds(.3));
            t.BeginAnimation( TextBox.BorderThicknessProperty, ta);

        }

As a minor (and obvious caveat): make sure that the starting width is the same as that on MouseLeave.

Conclusion

That’s all the animations and effects that I could think of. If you know of, or can come up with any more then if you eitjer add them in the comments, or contact me (www.twitter.com/paul_michaels or [email protected]) and I’ll add them in.

In the next (and final) post, I’ll focus on the differences in WinRT / Windows Phone 8.

Animation in XAML (Part 3)

Introduction

In this article, I’m going to expand on the first posts, by providing an alternative way to chain animations. In this article http://pmichaelsdev.wordpress.com/2013/10/29/animation-in-xaml-part-1/, I showed how to use the BeginTime property to do this; and that works fine; however, I did come across, what appeared to me to be, a slightly more elegant way of doing this: events.

Just for the sake of being different, I’ll use a different animation

Using Events to Chain Animations in WPF

Let’s start by creating a button that spins when you click it. The code isn’t too dis-similar to that in Part 1. Let’s have a look at the XAML first:

         <Button x:Name="SpinAndDisappear" Width="200" Height="50" Content ="Don't press me" Click="SpinAndDisappear_Click"
                RenderTransformOrigin="0.5, 0.5">
            <Button.RenderTransform>
                <RotateTransform/>
            </Button.RenderTransform>
        </Button>

Two things to note here: The RenderTransformOrigin will make it spin round the centre. Remove that and it’ll spin round the top left corner (and that would be just silly); and the RotateTransform section. That has to be there in order for WPF to know it can rotate the button.

Okay, here’s the code to spin the button:

         private void SpinAndDisappear_Click( object sender, RoutedEventArgs e)
        {
            Storyboard spin = (Storyboard )FindResource("sbSpin");
            spin.Begin( this);

        }

If you’ve been paying close attention, you’ll notice that this won’t work (even without running it and getting an error saying it can’t find the storyboard!). Here’s what the storyboard should look like:

    <Window.Resources >
        <Storyboard x:Key="sbSpin">
            <DoubleAnimation
              Storyboard.TargetName="SpinAndDisappear"
              Storyboard.TargetProperty="(Button.RenderTransform).(RotateTransform.Angle)"
              From="0"
              To="360"
              Duration="0:0:3" />
        </Storyboard>
    </Window.Resources >

That’s better, try that and you’ll have a spinning button.

Okay, so it spins. It’s not that impressive to be honest. Lets add another effect to the storyboard to make it more impressive (the clue to what that will be is in the name of the button). Let’s create that effect now:

     <Window.Resources>;
        <Storyboard x :Key="sbDisappear">
            <DoubleAnimation
                Storyboard.TargetName="SpinAndDisappear2"
                           Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleX)"
                           From="1" To ="0" Duration="0:0:0.2"/>
            <DoubleAnimation
                Storyboard.TargetName="SpinAndDisappear2"
                           Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleY)"
                           From="1" To ="0" Duration="0:0:0.2"/>
        </Storyboard>

If you’re starting to think this is getting repetitive then there’s a reason (that you’re thinking that – it is).

Now, let’s hook that in, first, just handle the Completed event of the spin:

         <Storyboard x :Key="sbSpin">
            <DoubleAnimation
              Storyboard.TargetName="SpinAndDisappear2"
              Storyboard.TargetProperty="(Button.RenderTransform).(RotateTransform.Angle)"
              From="0"
              To="360"
              Duration="0:0:3" Completed ="DoubleAnimation_Completed" />
        </Storyboard>

Finally, here’s the code for the DoubleAnimation_Completed:

         private void DoubleAnimation_Completed( object sender, EventArgs e)
        {
            Button b = ( Button)SpinAndDisappear;

            DoubleAnimation da = new DoubleAnimation (b.Width, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.WidthProperty, da);

            DoubleAnimation da2 = new DoubleAnimation (b.Height, 0, TimeSpan.FromSeconds(.5));
            b.BeginAnimation( Button.HeightProperty, da2);

        }

Again, not rocket science, but probably the least familiar thing so far. Basically, I’m taking a reference to the button, creating a DoubleAnimation and starting it (twice, one for width and one for height).

But that looks a bit odd… and seems useless

That’s it; you now have a button that spins, and then disappears. Okay, well, wouldn’t it be much better if it just span and disappeared at the same time?

Yes!

Next post!

Animation in XAML (Part 2)

Introduction

This is the second of my series of posts on animation, using WPF and XAML. In this post, I’m looking at how we can control an animation in WPF using code behind, and also, how two animations can be triggered simultaneously.

Button Animation in WPF with code-behind

The problem with a statement like this, is that you can pretty much replicate anything in XAML in code, so you can do everything in code, some, a little or nothing. So far, I’ve come across three approaches that make sense to me. In this article I’ll cover triggering animations from code behind; following articles will cover creating animations for elements that have the transform set in XAML, and finally, no XAML at all!

Triggering an animation from code

There’s little point in re-explaining the XAML; it’s essentially the same XAML that I’ve shown in the first post. It looks like this:

    <Window.Resources>
        <Storyboard x :Key="sbExpand">
            <DoubleAnimation
                Storyboard.TargetName="codebehindbutton"
                Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleX)"
                From="0" To ="1.2" Duration="0:0:0.3"/>
            <DoubleAnimation
                Storyboard.TargetName="codebehindbutton"
                Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleY)"
                From="0" To ="1.2" Duration="0:0:0.3"/>
       
            <DoubleAnimation
                Storyboard.TargetName="codebehindbutton"
                Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleX)"
                From="1.2" To ="1" Duration="0:0:0.3"
                BeginTime="0:0:0.3"/>
            <DoubleAnimation
                Storyboard.TargetName="codebehindbutton"
                Storyboard.TargetProperty="(Button.RenderTransform).(ScaleTransform.ScaleY)"
                From="1.2" To ="1" Duration="0:0:0.3"
                BeginTime="0:0:0.3"/>
        </Storyboard>
  

So, there’s a few things to note here:
– The storyboard is not part of the button definition; it’s actually part of the Window.Resources.
– We don’t use a named transition, but instead, specify the button name; however, we still have to tell the button that it has a transition:

    <Button Name ="codebehindbutton" Width="200" Height="150" Click="Button_Click" BorderThickness="2" Content="Don't Click Me">
          <Button.RenderTransform>
              <ScaleTransform 
                         ScaleX="1" ScaleY ="1" CenterX="100" CenterY="175"  />
          </Button.RenderTransform>
    </Button>

Generally speaking, there’s nothing new. The same transformation, the same effect; the only difference is that it’s defined as a resource for the Window rather than for the Button.

So, now we get to the crux; now that it doesn’t fire on a button event, how does it get fired? As usual with these things, it’s surprisingly easy when you look at the code:

    Storyboard sb = (Storyboard )FindResource("sbExpand");
    sb.Begin( this);

You also have access to the storyboard itself; for example, try this:

    Storyboard sb = (Storyboard )FindResource( "sbExpand");
    sb.AutoReverse = true;
    sb.Begin( this);

Multiple Animations

Cool eh?

Additionally, if you had two animations to start at the same time; this would be the way. For example, add the following label to your page:

         <Label x :Name="lblHello" Content="Spin Me!" Margin ="50,152,417,250" Width="50" Height="30"
               RenderTransformOrigin="0.5,0.5">
            <Label.RenderTransform>
                <RotateTransform/>
            </Label.RenderTransform>
        </Label>

And the following storyboard definition:

         <Storyboard x :Key="sbdLabelRotation">
            <DoubleAnimation
              Storyboard.TargetName="lblHello"
              Storyboard.TargetProperty="(Label.RenderTransform).(RotateTransform.Angle)"
              From="0"
              To="360"
              Duration="0:0:3"
              RepeatBehavior="4x" />
        </Storyboard>

(This was taken from the Laurent Bugnion article on the same subject http://www.galasoft.ch/mydotnet/articles/article-2006102701.aspx).

Now, try running both animations together:

             Storyboard sb = (Storyboard )FindResource("sbExpand");           
            sb.Begin( this);

             Storyboard sbdLabelRotation = (Storyboard)FindResource("sbdLabelRotation" );
            sbdLabelRotation.Begin( this);

Conclusion

So, both animations run at the same time. Admittedly, I’m not strictly sure what you could do with this particular animation; it’s certainly not my intention that WPF apps start taking a mid ’90s web-site feel!

In this article, we looked at controlling pre-defined storyboard definitions in code. In a future article, I intend to cover the creation of an animation from within code.