Mozilla

Animations Articles

Sort by:

View:

  1. Treat Open Source Like a Startup

    What am I getting myself into?

    I was never an open source contributor. I had never even filed a GitHub issue. I considered myself an entrepreneur who simply happened to be technical.

    But when the startup I wanted to build needed something that didn’t exist, I followed an unprecedented whim and paused everything I was working on. I pulled a hard left, and I wound up spending three months working full-time on a project that I needed ASAP. Equally as motivating, I knew that other developers needed it too.

    So, I switched hats. I became an insanely focused, sleeping-isn’t-allowed developer.

    The outcome was an animation engine that drastically improved UI performance and workflow across all devices. See it at VelocityJS.org. It’s a powerful JavaScript tool that rivals the performance of CSS transitions. The trick? Simple: In contrast to jQuery (which was initially released in 2006), I was building an engine that incorporated 2014’s performance best practices from the ground-up. No legacy layers; no bloat. Not a Swiss Army knife; a scalpel.

    But, throughout my solitary confinement, I was genuinely concerned that I was building something for a customer base of one — myself.

    I eventually came to realize that switching hats was actually the wrong approach. I was never supposed to take my startup hat off. (Since normal people don’t wear two hats at once, this is where my metaphor breaks down.)

    This is the story of that realization.

    Success

    Let’s momentarily jump ahead three months — to the time of Velocity’s release. Pardon me for a moment while I gloat:

    • Within three days, Velocity reached the top of Hacker News and programming subreddits a total of four times.
    • Within nine days, Velocity amassed 2400 GitHub stars.
    • Within two weeks, Velocity topped the CodePen charts with multiple demos reaching 10,000 views each (codepen.io/rachsmith/pen/Fxuiacodepen.io/okor/pen/fJIEF, and codepen.io/sol0mka/full/kzyjJ).
    • Countless business, front-end platforms, and web agencies migrated to Velocity (examples: everlane.com, discover.typography.com, apartmentlist.com).

    How was this possible? Because I treated Velocity like I treated my businesses: First, there’s development. That’s 10%. Then, there’s marketing. That’s 90%.

    The perspective shift I underwent midway through development was to commit to the following mantra: However much time I wound up spending on development, I would spend even more time on marketing.

    After all, that was the time-split I experienced with my startups. I didn’t see a single reason why it should be different for this project. User acquisition is user acquisition.

    Ultimately, if you develop a startup or an open source project intended for public use, and nobody uses it… you failed. It doesn’t matter how clever it was. It doesn’t matter what technical challenges you overcame.

    Unfortunately, however, the peculiar reality of OSS growth hacking is that there’s a stigma attached to it: The act of marketing invokes pitching, rubbing shoulders, begging, and bribing. It’s stereotypically personified as an overeager, two-bit hustler wearing a cheap shirt and an even cheaper tie. This clashes with our ideals of open source — which itself is stereotypically personified as a headstrong and idealistic code warrior wearing a cheap shirt and an even cheaper haircut.

    I’ll quote GitHub’s Zach Holman to get to the root of the dichotomy, “We like to think that open source is pure; that it’s unadulterated. That marketing an open source project is silly. That’s just silly.” – ZachHolman.com

    To put it bluntly, if you want your open source project to have an impact, you need to step out of your coder bubble. After all, if you build something amazing — and you market it effectively — you’re doing everyone a favor. Not just yourself.

    The best part is, the more people that know about your work, the more people there are to contribute: Bugs get discovered sooner. Useful features get pitched more often.

    And don’t worry — being seen publicly marketing your project doesn’t frame you as an egotistical developer. It frames you as someone who’s passionate. If you take the time to appreciate the fact that more people benefiting from your hard work is a major motivation in your pursuit of open source, then you’ll realize that hustling on behalf of your project fits exactly within your pre-existing ideals.

    Open source growth hacking

    If you look closely at the current open source landscape, those who most often reach the top of GitHub’s charts are developer figureheads with pre-existing followings, and major companies sharing components of their internal stack.

    Looking at this month’s GitHub’s trending chart, the top ranking projects that aren’t educational resources (link collections, tutorials, etc.) include: Pop (Facebook), Atom (GitHub), Quill (Salesforce), Velocity (Me!), Mail-in-a-Box (individual), Famous (Famous), syncthing (individual), betty (individual), Isomer (individual), Bootstrap (Twitter), Angular (Google), PourOver (NY Times).

    There’s a fair representation of individuals in there, but it’s typically corporations that dominate open source marketing. The reality, however, is that these corporations employ developers that are no better than you or I. There’s no inherent natural selection driving the popularity of their projects versus yours

    Fight to get your project out there. Or sit back and watch the marketing teams of huge companies drown your voice out.

    Velocity.js CodePen Demo

    That’s enough with waxing poetic and analyzing the current landscape. Let’s dive into the meaty details: How exactly did I market Velocity?

    • I pre-wrote advanced drafts for major web development blogs to consider publishing. By presenting the editors with the full goods upfront — not a pitch, not an outline — I minimized their workload, making it very easy for them to say “yes.” I also made sure to wait until I had enough GitHub stars (from Hacker News coverage, etc.) before pitching. And, most importantly, I had a strong thematic focus for each article: One article was exclusively about performance, and the other was exclusively about UI workflow. In both cases, I minimized the amount of attention spent pitching Velocity, and focused instead on educating readers about the respective topic. Blogs don’t want to publish a giant ad on your project’s behalf; they want content that their readers will thank them for.
    • I found out where my power-users were. This advice is common in the startup world: Find your core 1,000 early adopters. It’s no different with open source. Who were the users that craved for a performant animation engine — that would do amazing things with it then show off their exploits to the world without me prompting them to? Web animation demo-sceners — that’s who; the passionate, hard-core devs who explore the intersection of technology and design. And, where do they hang out? CodePen.io. I reached out to the demoers whose work I greatly admired, and I gave them access to a pre-release version of Velocity. Sure enough, they eventually pumped out something amazing for me to share.
    • To ensure that new developers always stumble into Velocity.js — even far past the point that I’m still proactively marketing the project — I embedded Velocity into every popular web developer resource that I could find. I pull-requested BentoBox.io and the popular GitHub repo for front end bookmarks. I pitched the Treehouse video blog guys. That was all just the start. I also have upcoming codecasts on Velocity’s workflow that code schools will be presenting to their students. Simply put, I made sure that every developer trying to master web animation would at some point hear about Velocity.
    • Most importantly, I wrote great documentation. To quote GitHub’s Zach Holman once again, “Documentation is marketing. The best part is that documentation is linkable. It’s indexable. It’s tweetable. Particularly if you have a nice, coherent one-page overview of your project that lets people jump in and immediately ‘get’ it.” To expand on Zach’s thoughts, I would frame an open source project’s documentation as what a landing page is to a startup. And make no mistake, you do have to pitch; you can’t merely document your API and call it a day. The developers reading your documentation are no different than anyone else; they have limited time, and they need to be convinced that your project is worth considering.

    When you have great documentation, posting to Reddit and Hacker News will take care of itself. Developers recognize their peers’ hard work, and they’re happy to spread the word.

    On this topic, do you know what the best-kept secret about open source marketing is? That it’s 100x times easier than startup marketing. It’s less work, and you’ll see success with a much greater degree of certainty. Why? Because developers — as compared to the average web user — are more willing to listen, are more willing to retweet, and are generally less skeptical of your marketing claims. Whereas most web users are tired of being pitched with trite social media products, developers are always on the hunt for better tools. Similarly, the web development press is much easier to get a response from than the mainstream tech news press is. The former is scrounging for good content to share with their users whereas the latter is drowning in a sea of half-backed startup pitches.

    Because of the marketing efforts I put into Velocity, and because of the project’s ensuing success, I have become highly motivated to continue working on open source projects.

    I am only just getting started: Velocity is the first in a trilogy of libraries that aim to change the way we visually interact with software. If you’re interested in staying on top of my UI exploits, say hello on Twitter: @Shapiro.

  2. Creating a Multiplayer Game with TogetherJS and CreateJS

    Bubble Hell Duel is a multiplayer HTML5 dogfighting game. The object of the game is to dodge bubbles launched from your opponent while returning fire. This game was written mainly as a prototype for learning and the source code is available on GitHub. You can try the game out in single or multiplayer here. Currently the game does not contain any sound effects but uses CreateJS and TogetherJS.

    screenshot

    In this post I would like to share some of my experiences when developing the game. Please share your thoughts in the comments if you agree or have other suggestions.

    Game Engines

    When developing a 2d game you can write you own engine or make use of some fantastic libraries that are available. After spending a few days looking at the various options available I decided to use CreateJS. As I have some experience with Flash, CreateJS made sense for my needs as there was not much of a learning curve. I also wanted to make use of some Flash animations and CreateJS supported this feature. I will elaborate a bit more on animations later in the article.

    As I am a C++ developer I believe emscripten is also a good choice. It allows C/C++ code to be compiled to JavaScript, which can be executed in the browser. I am of the opinion that the static type checking and compile-time optimizations are great assets when developing large code bases. I have used emscripten before and it works very well, but for this project I wanted the fast and convenient prototyping capabilities of JavaScript. I also wanted to expand my JavaScript knowledge.

    I’d like to mention a few other libraries that seem very interesting: Cocos2d-x is making an emscripten port and they already support HTML5 binding. I also like pixi.js as it provides a webGL renderer but also supports Canvas fallback when the browser does not support webGL.

    C++ vs JavaScript

    At first I was a little bit worried about the performance of JavaScript, and that was the reason my decision between using CreateJS or emscripten was difficult. Fortunately a simple benchmark showed that a naive collision detection algorithm with about 400 balls on screen could still reach 40+ fps, which was enough for my simple experiment.

    As someone who has coded more in C++ than JavaScript I loved how quickly I could translate my thoughts into code and test them out on multiple browsers. On the other hand it was not very comfortable debugging my JavaScript. C++ compilers are quite good at pointing out misspellings and other mistakes that cause runtime issues. While the “use strict” directive and other mechanisms like closure compilers have their purpose they were not very helpful to me especially when variables became undefined. Rooting for the cause of errors can be somewhat difficult comparatively.

    As an example of difficult debugging, I encountered the following issue. I was using float numbers for coordinates and other geometric values like angles. These values were passed to the other player using the TogetherJS.send method for synchronization:

    var player = { x: 10.0, y: 10.0 };
    TogetherJS.send({type:'sync',x:player.x,y:player.y});
    TogetherJS.hub.on('sync', function(msg){
        enemy.x = msg.x;
        enemy.y = msg.y;
    });

    This worked, but lots of decimals were sent in this way, so I decided to relax the accuracy:

    TogetherJS.send({type:'sync', x:Math.round(player.x), y:Math.round(player.y) });

    Then I thought integers might not be accurate enough for collision detection, so I added more digits to the messages:

    TogetherJS.send({type:'sync', x:player.x.toFixed(2), y:player.y.toFixed(2) });

    While this seemed a reasonable solution, it actually induced a bug that was very hard to find and I did not notice it until I tested the game after implementing some more features. I noticed while playing the game the opponent would never move.

    It took me hours in debugging before I could locate the cause. I do not think I would have made this mistake using C++.

    If you would like to see this bug in action take a look at this jsFiddle project. Look at the three canvas tag outputs and you will notice the third canvas contains the bug. This issue occurs because toFixed returns a string representation.

    I am not sure using a closure compiler would have avoided this issue, but I did find in another project that it definitely helps with optimizations.

    Animation with Flash

    As with most games I wanted to use a good deal of animation. I was very familiar with creating animations in Flash and found that CreateJS supported several ways of consuming the Flash animations and presenting them in HTML5. CreateJS is a set of libraries and tools used to create interactive HTML5 content. So by using CreateJS I could consume my animations as well as use the other libraries available for loop handling, resource management and in the future, sound manipulation. For a quick introduction to CreateJS take a look at this video.

    CreateJS, which Mozilla now sponsors, offers great support for Flash animations.

    There are two ways of using Flash animations in HTML5 with CreateJS. The first option is to directly export the Flash animation in a way that you can access all the elements in their original form, including paths, transformations and tweens. The advantage to this approach is that it produces smaller files, and CreateJS allows you to transfer them into a sprite sheet on the client side, for faster rendering. Adobe Flash CS6 offers the CreateJS Toolkit plugin that allows the designer to export all the content of an animation to HTML5 files. This generally results in a JavaScript file with all the graphics and tweens, an HTML file, and a set of image files. You can open up the HTML document in your browser and see the animation.

    Another option is to export the animation into a sprite sheet, that is an image containing all the frames with a JavaScript file describing the position and size of each frame. These files can be easily integrated into HTML based games or applications via the SpriteSheet class in CreateJS. This is the approach I used for this game. To see the code where I use the SpriteSheet have a look at this link. If you want some more detail on this approach take a look at this video.

    I should also note that you can use a tool called Zoë to export directly to a sprite sheet or a JSON file from a Flash Animation as well.

    marisa

    The above image is an example of a sprite sheet that I use in the game and was generated as described above. The original image came from the game Touhou Hisouten ~ Scarlet Weather Rhapsody, which is availabe at http://www.spriters-resource.com.

    Multiplayer with TogetherJS

    On my first iteration of the code the game was not multiplayer. Originally it was a single-player bullet hell game, with a boss foe randomly moving across the screen. I could not last more than 30 seconds before succumbing to withering fire. It was interesting enough that I thought multiplayer would be exciting.

    I had heard of Together.js not long after it was released. The jsFiddle project is powered by Together.js and offers an impressive collaboration mode. This led me to using Together.js in my game. It is also very nice that Mozilla offers a default hub server simplifying the process of creating a multiplayer web based game. To learn more about Together.js be sure to check out this article.

    It was easy and comfortable integrating Together.js into my game, as it works like other event dispatcher/listeners frameworks.

    With Together.js, I was able to implement random match and invitation only multiplayer modes in the game. I did face a few design challenges that I had to overcome when designing the communication protocol.

    First off, I did not put code in to prevent cheating with two-party communications and assumed a certain level of trust between players. In the game design currently all collision detection of a player is done locally. Theoretically if you block corresponding messages you can mask that you have taken damage.

    Another area that I hacked a bit is that the bubbles of the enemy avatar are generated locally and randomly. This means that the bubbles seen from your character avatar are not necessarily the same as your opponent is seeing.

    In practice neither of these shortcuts should ruin the fun of the game.
    I did encounter a couple of issues or caveats with Together.JS.

    • I did not find a way to disable the cursor updating in Together.js. While this is useful in collaborative tools I did not need it in my game.
    • I am using Together.js in an asymmetric way, where both players see themselves as the red skirted Avatar (Reimu). This allows for easier placement of the player at the bottom of the screen and the opponent at the top. This also means that when you move the main player from an opponent’s view of the game your move is seen as the opponents move and vice versa.

    The Fun of Making Mistakes

    There are two visual effects in the game that came as unexpected surprises:

    • When a round finishes and the message ‘You Win’ or ‘You Lose’ appears, the time is frozen for a few seconds. This acts like a dramatic pause.
    • When a charge attack is released, the bullets are fixed and then gradually blown away toward the enemy.

    Neither of these effects was designed in this way. I didn’t want the pause and I wanted the bullets to continue rotating around the player upon releasing. However I made mistakes, and the result seemed to be much better than I had planned, so they made the final cut.

    Conclusion and Future Plans

    It is always fun learning new things. I like the fact that I could prototype and visualize pretty quickly. In the future I might add more patterns for the bullet curtains, and a few sound effects. In addition I will probably also draw more background images or possibly animate them.

    While developing the game I did realize in order to get a natural and intuitive feel required more effort than I expected. This is something I have always taken for granted while playing game.

    The code is open source, so feel free to fork and play. Be sure to comment if you have any suggestions for improving the game or the existing code.

  3. Introducing the Canvas Debugger in Firefox Developer Tools

    The Canvas Debugger is a new tool we’ll be demoing at the Game Developers Conference in San Francisco. It’s a tool for debugging animation frames rendered on a Canvas element. Whether you’re creating a visualization, animation or debugging a game, this tool will help you understand and optimize your animation loop. It will let you debug either a WebGL or 2D Canvas context.

    Canvas Debugger Screenshot

    You can debug an animation using a traditional debugger, like our own JavaScript Debugger in Firefox’ Developer Tools. However, this can be difficult as it becomes a manual search for all of the various canvas methods you may wish to step through. The Canvas Debugger is designed to let you view the rendering calls from the perspective of the animation loop itself, giving you a much better overview of what’s happening.

    How it works

    The Canvas Debugger works by creating a snapshot of everything that happens while rendering a frame. It records all canvas context method calls. Each frame snapshot contains a list of context method calls and the associated JavaScript stack. By inspecting this stack, a developer can trace the call back to the higher level function invoked by the app or engine that caused something to be drawn.

    Certain types of Canvas context functions are highlighted to make them easier to spot in the snapshot. Quickly scrolling through the list, a developer can easily spot draw calls or redundant operations.

    Canvas Debugger Call Highlighting Detail

    Each draw call has an associated screenshot arranged in a timeline at the bottom of the screen as a “film-strip” view. You can “scrub” through this film-strip using a slider to quickly locate a draw call associated with a particular bit of rendering. You can also click a thumbnail to be taken directly to the associated draw call in the animation frame snapshot.

    Canvas Debugger Timeline Picture

    The thumbnail film-strip gives you get a quick overview of the drawing process. You can easily see how the scene is composed to get the final rendering.

    Stepping Around

    You might notice a familiar row of buttons in the attached screenshot. They’ve been borrowed from the JavaScript Debugger and provide the developer a means to navigate through the animation snapshot. These buttons may change their icons at final release, but for now, we’ll describe them as they currently look.

    Canvas Debugger Buttons image

    • “Resume” – Jump to the next draw call.
    • “Step Over” – Goes over the current context call.
    • “Step Out” – Jumps out of the animation frame (typically to the next requestAnimationFrame call).
    • “Step In” – Goes to the next non-context call in the JavaScript debugger

    Jumping to the JavaScript debugger by “stepping in” on a snapshot function call, or via a function’s stack, allows you to add a breakpoint and instantly pause if the animation is still running. Much convenience!

    Future Work

    We’re not done. We have some enhancements to make this tool even better.

    • Add the ability to inspect the context’s state at each method call. Highlight the differences in state between calls.
    • Measure Time spent in each draw call. This will readily show expensive canvas operations.
    • Make it easier to know which programs and shaders are currently in use at each draw call, allowing you to jump to the Shader Editor and tinkering with shaders in real time. Better linkage to the Shader Editor in general.
    • Inspecting Hit Regions by either drawing individual regions separately, colored differently by id, or showing the hit region id of a pixel when hovering over the preview panel using the mouse.

    And we’re just getting started. The Canvas Debugger should be landing in Firefox Nightly any day now. Watch this space for news of its landing and more updates.

  4. The making of a hack – Media Query Mario

    Like any developer, I love any shiny new tech demo that finds its way into my browser; some of the things people are putting together absolutely blows my mind with the level of creativity and technical skill on show.

    After attending WebDevConf 2012 in mid October, I felt the usual heightened sense of inspiration that a good conference gives us all. On my way back to London, I happened to see a tweet about the current Mozilla Dev Derby in my Twitter stream and, still inspired, thought about creating something to enter myself. That something turned into a tech demo called Media Query Mario; a mash up of Media Queries, CSS3 Animations and HTML5 audio.

    Where to start?

    Thinking of the idea came as a result of which new technologies I wanted to experiment with the most at the time. I had been meaning to delve into CSS animation for some time and combining this with media queries – the focus of that months Dev Derby – seemed pretty logical. Letting the CSS fire off the animations instead of needing JavaScript to do this seemed like a very natural fit.

    Choosing Mario 3 for the animation was simply the first thing that popped into my head. I wanted the animation to be a side scrolling 2D affair and being a retro game nerd, Mario instantly came to mind. Anyone with more than a fleeting interest in 2D Mario games would then see that Mario 3 was the only real choice for my animation (although I’m free to argue against any opposing opinions on the ‘best’ 2D Mario game anytime!)

    One question I’ve been asked since putting the demo out is: why choose CSS animations when other technologies may have been more suitable? The main reason is that I simply wanted to see what they could do. There are plenty of demos showcasing just how awesome canvas and SVG are; my demo is by no means meant to advocate the use of CSS animations over those technologies. I just wanted to give a decent benchmark of where CSS animation is at right now, and at least add them to the conversation when people are choosing which technology is right for their project.

    There was only one rule I set myself when starting to put together the demo – I wanted to stick rigidly to animating using CSS wherever possible. If it was possible to do something in CSS, I wanted to use it, irrespective of performance or how fiddly it was to implement. I’ll come back to how I think it performed in retrospect later.

    Push any button to start

    One of the earliest issues I came up against was knowing what width the user would be viewing the animation at. This was not only important in terms of what size to design the animation to, but especially in terms of how much of the level was on show at any one time. The more of the level on show, the more I would need to animate at any one time.

    After a little thought around how Mario 3 itself was presented, it made sense to make use of the original menu screen to help control this. As well as acting as a holding screen while the animation assets loaded, it would ensure the user resized their browser window down to a dimension I could specify, before then allowing the animation to be started. This was controlled by adding a conditional media query hiding the animation start button:

    @media screen and (max-width: 320px), (min-width: 440px) {
        .startBtn {
            display:none;
        }
    }

    Planning the actual animation itself, I wanted to mirror the way the original game would have been played as much as possible. To help with this I found a video clip that traversed through the level at a pace that I could replicate. This helped me plan the image and sound assets I would need, the speed of the animation and started the thinking around how to animate different enemies and power-ups throughout the level.

    With the structure of the demo planned out, I now just needed the assets. As you might expect, you don’t have to search for too long online to find original game images, sprites and sound files. For my demo, I used NESmaps and Mario Mayhem for the level map and character/object sprites and The Mushroom Kingdom for the sound files. I had to do a small amount of image editing myself, but these gave me a really great start.

    You can view the final spritesheet I used for the animation below.

    Letsa Go!

    So I had an idea planned out and had found my assets; I was ready to start putting it all together in code.

    First, I set about learning the specifics of CSS3 animations. A couple of resources really helped me out; MDN is always a great place to start and is no exception for CSS animations. I would also recommend any of these great articles by Peter, Chris or David – all provide an excellent introduction to getting started with CSS3 animations.

    I won’t look to replicate the depth those articles cover, but will highlight the key properties I made use of in the demo. For brevity, I’ll be covering the CSS3 syntax unprefixed, but if trying any of this out for yourself, prefixes should be included in your code to ensure the animations work across different browsers.

    A quick development tip worth mentioning when using newer CSS3 features such as CSS animations, is that using a preprocessor, such as LESS or SASS, is a massive lifesaver and something I’d highly recommend. Creating mixins that abstract the vendor prefixes out of the code you are directly working with helps keep visual clutter down when writing the code, as well as saving a whole load of time when changing CSS property values down the line.

    Before we get into specific techniques used in the demo, we need to understand that an animation consists of two main parts; the animation’s properties and its related keyframes.

    Animation Properties

    An animation can be built up with a number of related properties. The key properties I made use of were:

    //set the name of the animation, which directly relates to a set of keyframes
    animation-name: mario-jump;
     
    //the amount of time the animation will run for, in milliseconds or seconds
    animation-duration: 500ms;
     
    //how the animation progresses over the specified duration (i.e. ease or linear)
    animation-timing-function: ease-in-out;
     
    //how long the animation should wait before starting, in milliseconds or seconds
    animation-delay: 0s;
     
    //how many times the animation should execute
    animation-iteration-count: 1;
     
    //if and when the animation should apply the rendered styles to the element being animated
    animation-fill-mode: forwards;

    The use of the animation-fill-mode property was especially important in the demo, as it was used to tell the animation to apply the final rendered styles to the element once the animation had finished executing. Without this, the element would revert to it’s pre-animated state.

    So for example, when animating an element’s left position 30 pixels from an initial position of 0px, if no animation-fill-mode is set, the element will return to 0px after animating. If the fill-mode is set to forwards the element will stay positioned at its final position of left: 30px.

    Keyframes

    The Keyframes at-rule lets you specify the steps in a CSS animation. At its most basic level this could be defined as:

    @keyframes mario-move {
        from { left:0px;   }
        to   { left:200px; }
    }

    Where from and to are keywords for 0% and 100% of the animation duration respectively. To show a more complex example we can also code something like this, which, relating back to the demo, animates Mario jumping between several platforms using multiple keyframes:

    @keyframes mario-jump-sequence {
        0% { bottom:30px; left: 445px; }
        20% { bottom:171px; left: 520px; }
        30% { bottom:138px; left: 544px; }
        32% { bottom:138px; left: 544px; }
        47% { bottom:228px; left: 550px; }
        62% { bottom:138px; left: 550px; }
        64% { bottom:138px; left: 550px; }
        76% { bottom:233px; left: 580px; }
        80% { bottom:253px; left: 590px; }
        84% { bottom:273px; left: 585px; }
        90% { bottom:293px; left: 570px; }
        100% { bottom:293px; left: 570px; }
    }

    So if the above animation was 1 second long, Mario would move from position bottom: 30px; left: 445px; at 0 seconds (0% through the animation) to bottom: 138px; left: 520px; during the first 200ms (or 20%) of your animation. This carries on like this throughout the keyframes defined.

    Animating the action

    Considering the above, the type of animations I created in the demo can be broken down into 3 broad categories:

    • Movement such as Mario jumping or a coin appearing out of a question box.
    • Spriting controls the background-image position of characters and objects in the animation.
    • Looping any animation that is to be repeated for x number of milliseconds or seconds.

    Movement

    Movement covers roughly 75% of all of the animations in the demo. For example, this includes character movement (i.e. Mario running and jumping), power-ups appearing and question boxes being hit. What makes each movement animation differ is the animation-timing-function, the animation-duration and the animation-delay properties.

    The animation-timing-function property helps control the speed of the animation over its duration. Wherever possible I used easing, such as ease-in or ease-in-out to save having to be too precise when defining animation keyframes. Where this didn’t create the effect I needed, I resorted to setting the animation-timing-function to linear and using the keyframes to specify the exact movement I required.

    An example a movement animation can be seen by this jump sequence.

    Spriting

    To control the image background-position of the characters and objects in the animation, I used the step-end timing-function:

    .mario {
        animation-timing-function: step-end;
        ...
    }

    Initially, I thought I may need to use JavaScript to control the image spriting by adding and removing classes to my elements. However, after experimenting with how the step-end timing keyword was implemented, I found it perfectly stepped through the keyframes I had defined, one keyframe at a time.

    To show this in action, take a look at the following examples, which show a simple Mario walking animation and Mario transforming after grabbing a power-up.

    Using step-end in this way wasn’t completely pain free however. To my frustration, when these sprite animations were stacked up over multiple media queries, I found that there was a glitch in WebKit that caused the animation to render differently to the keyframes I had defined. Admittedly, the use of CSS animations in this way is an edge case for browser rendering, but I have filed it as a bug in Chromium, and am hopeful this will be looked at in the future and ironed out.

    LOOPING

    Whenever an animation needed to be repeated over a period of time, looping was defined by adjusting the animation-iteration-count:

    //the animation repeats 5 times
    animation-iteration-count: 5;
     
    //the animation repeats infinitely
    animation-iteration-count: infinite;

    An example of this from the demo would be the rotation of the fireball].

    Through these 3 types of animation, the whole demo was constructed. The final layer was to add in the audio.

    Adding Audio

    Although I had previously downloaded all of the sound files I needed in .wav format, I had to convert them into a format that was usable with HTML5 audio; .ogg and .mp3. I used Switch Audio Convertor (on Mac) to do this, but any good audio conversion software should do the job.

    Once I had the converted files, I needed to detect which file type to serve to the browser. This required a couple of lines of JavaScript to detect support:

    var audio = new Audio(); //define generic audio object for testing
    var canPlayOgg = !!audio.canPlayType && audio.canPlayType('audio/ogg; codecs="vorbis"') !== "";
    var canPlayMP3 = !!audio.canPlayType && audio.canPlayType('audio/mp3') !== "";

    I then created a function to set some default audio parameters for each sound, as well as setting the source file based on the format previously detected to be supported by the browser:

    //generic function to create all new audio elements, with preload
    function createAudio (audioFile, loopSet) {
        var tempAudio = new Audio();
        var audioExt;
     
        //based on the previous detection set our supported format extension
        if (canPlayMP3) {
            audioExt = '.mp3';
        } else if (canPlayOgg) {
            audioExt = '.ogg';
        }
     
        tempAudio.setAttribute('src', audioFile + audioExt); //set the source file
        tempAudio.preload = 'auto'; //preload the sound file so it is ready to play
     
        //set whether the sound file would loop or not
        //looping was used for the animations background music
        tempAudio.loop = (loopSet === true ? true : false);
     
        return tempAudio;
    }
    var audioMarioJump = createAudio("soundboard/smb3_jump"); //an example call to the above function

    It was then just a case of playing the sound at the correct time in sync with the animation. To do this, I needed to use JavaScript to listen for the animation events animationstart and animationend – or in WebKit, webkitAnimationStart and webkitAnimationEnd. This allowed me to listen to when my defined animations were starting or ending and trigger the relevant sound to play.

    When an event listener is fired, the event returns the animationName property, which we can use as an identifier to play the relevant sound:

    mario.addEventListener('animationstart', marioEventListener);
     
    function marioEventListener(e) {
        if (e.animationName === 'mario-jump') {
            audioMarioJump.play();
        }
    }

    If you have multiple animationstart events for one element, such as Mario in my demo, you can use a switch statement to handle the animationName that has triggered the event listener.

    Since writing the demo, I have found that you can also target individual keyframes in an animation by using the Keyframe Event JS shim by Joe Lambert, which gives you even more control over when you can hook into your animation.

    Game Complete

    The response to the demo has been more positive than I’d ever hoped for since it was released. Like any hack, there are things I’d like to go back and improve with more time, but I think it’s more valuable to put what I learned into my next project. I think that the demo has shown that CSS animations can be used to create some amazing effects from fairly simple code, but also brought one bigger issue to my mind while putting it together.

    While complex CSS animations actually perform very well, the creation of such an animation is fairly longwinded. Sure, there are tools out there designed to help with this, such as Adobe Edge Animate and Sencha Animator, but both of these output CSS animations wrapped up in JavaScript. This seems a massive shame to me, as the power of CSS animations is surely in the fact that they shouldn’t have to rely on another technology to execute. I’m not sure if there is a potential way around this, other than coding it by hand yourself, but if anyone knows of any I’d be interested to hear of them in the comments.

    Going back to my earlier comment about comparing CSS animations to using canvas and SVG, I think all have a place at the table when discussing what technology to use for animation. However, the sooner the barrier of time spent to craft complex animations like this one can be lowered, the more relevance, and potential use cases, CSS animations will have in the projects that we do.

  5. Calculated drop shadows in HTML5 canvas

    One of the best new features of HTML5 when it comes to visual effects is the canvas element and its API. On the surface, it doesn’t look like much – just a rectangle in the page you can paint on and wipe. Much like an etch-a-sketch. However, the ability to transform, rotate and scale its coordinate system is very powerful indeed once you master it.

    Today I want to quickly show how you can do (well simulate) something rather complex with it, like a calculated drop shadow on an element. To see what I mean with this, check out the following demo which is also available on the Demo Studio:


    See animated version on JSFiddle

    (This is using JSFiddle to show you the demos, so you can click the different tabs to see the JavaScript and CSS needed for the effects. All of the demos are also available on GitHub.)

    As you can see, the shadow becomes more blurred and less pronounced the further away the “sun” is from it. You can use the mouse to see the effect in the following demo:


    See mouse enabled demo on JSFiddle

    Let’s take a look how that is done. The first step is to have a canvas we can paint on – you do this simply by having a mouse detection script (which we used for years and years) and a canvas with access to its API:


    See step one on JSFiddle

    Click the play button of the above example and you see that you can paint on the canvas. However, the issue is that you keep painting on the canvas instead of only having the orb follow the cursor. To do this, we need to wipe the canvas every time the mouse moves. You do this with clearRect()


    See step two on JSFiddle

    Running the above example now shows that the orb moves with the mouse. Cool, so this is going to be our “sun”. Now we need to place an object on the canvas to cast a shadow. We could just plot it somewhere, but what we really want is it to be in the middle of the canvas and the shadow to go left and right from that. You can move the origin of the canvas’ coordinate system using translate(). Which means though that our orb is now offset from the mouse:


    See step three on JSFiddle

    If you check the “fix mouse position” checkbox you see that this is fixed. As we move the coordinate system to the half of the width of the canvas and half of its height, we also need to substract these values from the mouse x and y position.

    Now we can draw a line from the centre of the canvas to the mouse position to see the distance using c.moveTo( 0, 0 );c.lineTo( distx, disty ); where distx and disty are the mouse position values after the shifting:


    See step four on JSFiddle

    In order to find out the distance of the shadow, all we need to do is multiply the mouse coordinates with -1 – in this demo shown as a red line:


    See step five on JSFiddle

    This gives us a shadow distance from the centre opposite of the mouse position, but we don’t want the full length. Therefore we can apply a factor to the length, in our case 0.6 or 60%:


    See step six on JSFiddle

    Now we are ready for some drop shadow action. You can apply shadows to canvas objects using shadowColor and its distance is shadowOffsetX and shadowOffsetY. In our case, this is the end of the red line, the inversed and factored distance from the mouse position to the centre of the canvas:


    See step seven on JSFiddle

    Now, let’s blur the shadow. Blurring is done using the shadowBlur property and it is a number starting from 0 to the strength of the blur. We now need to find a way to calculate the blur strength from the distance of the mouse to the centre of the canvas. Luckily enough, Pythagoras found out for us years ago how to do it. As the x and y coordinate of the mouse are the catheti of a right-angled triangle, we can calculate the length of the hypothenuse (the distance of the point from the centre of the canvas) using the Square root of the squares of the coordinates or Math.sqrt( ( distx * distx ) + ( disty * disty ) ).

    This gives us the distance in pixels, but what the really want is a number much lower. Therefore we can again calculate a factor for the blur strength – here we use an array for the weakest and strongest blur blur = [ 2, 9 ]. As the canvas itself also has a right-angled triangle from the centre to the top edge points we can calculate the longest possible distance from the center using longest = Math.sqrt( ( hw * hw ) + ( hh * hh ) ) where hw is half the width of the canvas and hh half the height. Now all we need to do is to calculate the factor to multiply the distance with as blurfactor = blur[1] / longest. The blur during the drawing of the canvas is the distance of the mouse position multiplied with the factor or currentblur = parseInt( blurfactor * realdistance, 10 );. We disregard blur values below the range we defined earlier and we have our blurred shadow:


    See step eight on JSFiddle

    In order to make the shadow weaker the further away the mouse is we can use the alpha value of its rgba() colour. The same principle applies as with the blur, we set our edge values as shadowalpha = [ 3, 8 ] and after calculating them from the distance we apply their inverse as the alpha value with c.shadowColor = 'rgba(0,0,0,' + (1 - currentalpha / 10) + ')';. This blurs and weakens the shadow:


    See step nine on JSFiddle

    You can do a lot more with this, for example we could also scale the sun orb the further out it gets or use a second shape to resize and blur it. You can also go completely overboard.

    Found a way to optimise this? Tell us about it!

  6. Rendering 3D with CSS and JavaScript with dom3d (guest post)

    James Long Today we have a guest post by James Long (@jlongster).

    James is the tech lead for mozilla.com on the Web Development team. James is passionate about interactive graphics on the open web.

    Today he explains how you can create 3D objects using CSS without having 3D transforms support. Take it away, James.


    Recently I was tinkering with CSS3 and I discovered that it enabled me to do primitive 3D rendering, which I found fascinating! This led to the creation of dom3d, a JavaScript library that uses CSS to render basic 3D objects.

    Now the question is: why? Aren’t canvas, WebGL, and even SVG better technologies to work with for this? Possibly. However, CSS is becoming a powerful language for describing complex effects and shapes, and we should experiment.

    Keep that in mind, because CSS definitely isn’t intended to do this, but it’s worth trying to see where we should take CSS in the future.

    Advantages

    Although this is more of an experiment, it has a few real world benefits:

    All rendering libraries available for the web (canvas, WebGL, SVG) require a canvas, which is a constrained box on the page with a specific width and height. It is not possible to render anything outside this box. The canvas also captures all DOM events (like clicks), even completely transparent sections. Theoretically, this could make it difficult to do effects that overlay large parts of the page or are somehow deeply integrated to the content.

    Using CSS, we aren’t constrained to a box, and the effect can overlay large portions of the page without covering any the the links or other content requiring interaction.

    Other advantages include no need to initialize canvas 2D or WebGL, and a simplistic API making it easy to pick up even if you don’t know much about 3D. It might be easier for kids to start playing around with this before they jump into WebGL or something else. Also, because it’s just a dump of DOM elements you can embed it anywhere (without animation).

    So keep in mind that this is a hack, but with the above advantages. This might be good for certain effects: 3D cursor, nav transitions, and others.

    How it works

    Three-D objects are just a bunch of triangles put together, so let’s start with one simple triangle. If we get that working, it’s a simple step forward to render multiple triangles to form a 3D object.

    Rendering a 3d triangle on a 2D screen involves something called “projection”. This is the act of taking a 3D point and projecting it onto a 2D screen. Plug in a 3D triangle to a simple math equation, and you get a 2D triangle representing how the 3D one would look on the screen.

    The math is remarkably simple but may seem weird if you aren’t familiar with linear algebra. You can take a look at the renderer code.

    Now comes the fun part: can you render any 2D triangle simply with CSS3 transforms? Turns out you can! It just takes some fiddling to figure out which transforms to generate. CSS3 transforms are composed of translate, scale, rotate, and skew values, and we need a few equations to compute these values for a specific 2D triangle.

    First, let’s take a simple DOM element and turn it into a triangle. We can do this with the linear-gradient background image (another way is border triangles).

    JSFiddle demo.

    Now let’s draw the following blue triangle with the points [20, 20], [50, 120], and [120, 30]. A vital step is to set a few initial reference points which set everything in the same space. Our equations will assume these coordinate spaces. This is how the points A, B, C and the side AB are related.

    Triangle comparison

    If we take a closer look at this, we can derive the transform values. First, get an idea of which angles and values we need and then use geometry to form the equations (in pseudo-code). The red box represents the DOM element, the form AB represents the side formed by points A and B, and rotation occurs clockwise.

    dissecting triangles

    rotation = atan2(AB.x, AB.y)
    AC' = rotate(AC, -rotation)
    width = AC'.x
    height = length(AB)
    skew = atan2(AC'.y, AC'.x)
    translate = A

    Awesome! Let’s try it out. Here is a live DOM element being transformed by applying each of our equations:

    JSFiddle demo.

    The resulting triangle matches our target triangle! Here is the final CSS:

    width: 93px;
    height: 104px;
    background: -moz-linear-gradient(-0.727211rad, #0000FF 50%, transparent 0pt);
    -moz-transform: translate(20px, 20px) rotate(-0.291457rad) skewY(0.391125rad);
    -moz-transform-origin: top left;

    Note: The tranform-origin: top left line is important. Normally transforms happen relative to the center of the element, but our equations assume the top left.

    Note: dom3d also generates code with the -webkit and -o prefixes for WebKit and Opera support.

    You can view the implementation of these equations. It turns out that these equations work for any triangle, as long as the points given are in counter-clockwise order, which is standard in the graphics world.

    Taking it all the way

    Since we can project a 3D triangle into 2D space and render it with CSS, all we have to do now is apply that to several 3D triangles to form a 3D object!

    We need some 3D data at this point. I used Blender to export a teapot into the simple OBJ file format and wrote a script to dump the data as JavaScript. Rendering all those triangles with this technique produces the following:

    JSFiddle demo.

    Teapot! However, we can do much better. A big part of the 3D effect is shading. If we calculate normals, a vector representing where the triangle is facing, and specify a light direction, we can take the dot product of the normal and light for each triangle to get flat shading. View the code for flat shading.

    JSFiddle demo.

    There are many tweaks that take this even further. For example, the above objects have z-indexing enabled. Without this, a triangle that is supposed to be behind another may actually appear on top because it was rendered later. The dom3d uses a heap to render the triangles from back to front.

    Real-time animation can be achieved with a setTimeout or requestAnimationFrame function that continually renders the object. The dom3d supports the scale, translate, yaw, and pitch transformations, but there’s nothing stopping you from modifying the object data however you like between renderings. See some examples over at the dom3d website.

    Here is the code which renders the teapot animation with dom3d:

    JSFiddle demo.

    It’s more appropriate for webpages to update an animation in response to user interaction instead of constantly rendering and hogging the CPU. See the pole example on the dom3d site for an example.

    Improvements and last thoughts

    The most interesting possibility with this is to include actual page elements as part of 3D objects. A navigation item could pop out and swirl around in 3d space, and the nav item is seamlessly transformed along with it.

    That’s where this hack starts to show its faults, though. Unfortunately this is a little too hacky to provide an appropriate web experience. Because it tricks DIVs into fake triangles, it removes the possibility of integrating any page elements with it. With the coming of 3D CSS transforms though, we can start building true 3D objects made up of any kind of page elements. The only restriction with 3D transforms is that the 3D objects need to built with rectangles instead of triangles.

    Other people have already experimented with 3D transforms, like building a pure CSS 3D city. There’s another cool library, Sprite3D, which provides a JavaScript API for building basic 3d objects from page elements.

    The most glaring problem with dom3d is the seams in the object, which appear in all browsers. Apparently there are a few bugs in rendering engines when stressing their CSS3 transforms and using linear-gradients!

    The dom3d library provides an API to work with all of this, but is hasn’t been documented very well yet. Feel free to browse the README and code on github. These APIs could be improved as well. It also provides an SVG rendering backend, seen here, but I don’t this is the right direction to take. We should focus on building basic 3D objects with page elements.

    This was a fun experiment and I’m excited by how fast and capable browsers are becoming. The web is an exciting platform and getting richer and more powerful every year!

  7. Animating with javascript: from setInterval to requestAnimationFrame

    Animating DOM elements[1] or the content of a canvas is a classical use case for setInterval. But the interval is not as reliable as it seems, and a more suitable API is now available…

    Animating with setInterval

    To animate an element moving 400 pixels on the right with javascript, the basic thing to do is to move it 10 pixels at a time on a regular interval.

    JSFiddle demo.

    An HTML5 game based on this logic would normally run at ~60fps[2], but if the animations were too complex or running on a low-spec. device (a mobile phone for instance) and processing a frame were taking more than 16ms, then the game would run at a lower framerate: when processing 1 frame takes 33ms, the game runs at 30fps and game elements move twice as slowly as they should. Animations would still look smooth enough, but the game experience would be altered.

    Animating at constant speed

    To animate at constant speed, we need to calculate the time delta since the last frame and move the element proportionally.

    Animating with requestAnimationFrame

    Since the interval parameter is irrelevant in complex animations, as there’s no guarantee that it will be honored, a new API has been designed: requestAnimationFrame. It’s simply a way to tell the browser “before drawing the next frame on the screen, execute this game logic/animation processing”. The browser is in charge of choosing the best moment to execute the code, which results in a more efficient use of resources[3].

    Here’s how an animation with requestAnimationFrame would be written.
    Note: Following code snippets don’t include feature detections and workarounds necessary to work in current browsers. Should you want to play with them, you should try the ready-to-use animLoop.js.

    Dealing with inactive tabs

    requestAnimationFrame was built with another benefit in mind: letting the browser choose the best frame interval allows to have a long interval in inactive tabs. Users could play a CPU intensive game, then open a new tab or minimize the window, and the game would pause[4], leaving resources available for other tasks.
    Note: the potential impact of such behavior on resource and battery usage is so positive that browser vendors decided to adopt it for setTimeout and setInterval as well[5].

    This behavior also means that the calculated time delta might be really high when switching back to a tab containing an animation. This will result in animation appearing to jump or creating “wormholes[6], as illustrated here.

    Wormholes can be fixed by clamping the time delta to a maximum value, or not rendering a frame when the time delta is too high.

    JSFiddle demo.

    Problems with animation queues

    Libraries such as jQuery queue animations on elements to execute them one after the other. This queue is generally only used for animations that are purposefully consecutive.
    But if animations are triggered by a timer, the queue might grow without bound in inactive tabs, as paused animations stack up in the queue. When switching back to affected tabs, a user will see a large number of animations playing consecutively when only one should happen on a regular interval:

    JSFiddle demo.

    This problem is visible in some auto-playing slideshows such as mb.gallery. To work around it, developers can empty animation queues before triggering new animations[7].
    JSFiddle demo.

    Conclusion

    The delays of setTimeout and setInterval and of course requestAnimationFrame are unpredictable and much longer in inactive tabs. These facts should be taken into account not only when writing animation logic, but in fps counters, time countdowns, and everywhere time measurement is crucial.

    [1] The DOM can now be animated with CSS3 Transitions and CSS3 Animations.
    [2] 1 frame every 16ms is 62.5 frames per second.
    [3] See the illustration of this fact on msdn.
    [4] The behavior of requestAnimationFrame in inactive tabs is still being worked on at the w3c, and might differ in other browsers.
    [5] See related Firefox bug and related chromium bug.
    [6] This term was first coined by Seth Ladd in his “Intro to HTML5 Game Development” talk.
    [7] See documentation of your js library, such as effects and stop() for jQuery.