Data Loading...

Web Animation using JavaScript- Develop & Design Flipbook PDF

Web Animation using JavaScript- Develop & Design


116 Views
81 Downloads
FLIP PDF 5.38MB

DOWNLOAD FLIP

REPORT DMCA

Web Animation using JavaScript DEVELOP AND DESIGN Julian Shapiro

WWW.PEACHPIT.COM

Web Animation using JavaScript: Develop and Design Julian Shapiro Peachpit Press www.peachpit.com To report errors, please send a note to [email protected] Peachpit Press is a division of Pearson Education. Copyright 2015 by Julian Shapiro Editor: Victor Gavenda Development editor: Margaret S. Anderson Project manager: Margaret S. Anderson Technical editor: Jay Blanchard Copyeditor: Gretchen Dykstra Production editor: David Van Ness Proofreader: Patricia Pane Compositor: Danielle Foster Indexer: Jack Lewis Cover design: Aren Straiger Interior design: Mimi Heft Notice of Rights All rights reserved. No part of this book may be reproduced or transmitted in any form by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior written permission of the publisher. For information on getting permission for reprints and excerpts, contact [email protected] Notice of Liability The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of the book, neither the author nor Peachpit shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the instructions contained in this book or by the computer software and hardware products described in it. Trademarks Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and Peachpit was aware of a trademark claim, the designations appear as requested by the owner of the trademark. All other product names and services identified throughout this book are used in editorial fashion only and for the benefit of such companies with no intention of infringement of the trademark. No such use, or the use of any trade name, is intended to convey endorsement or other affiliation with this book. ISBN-13: 978-0-134-09666-7 ISBN-10: 0-134-09666-5 9 8 7 6 5 4 3 2 1

Printed and bound in the United States of America

I dedicate this book to people who play Counter-Strike. And to people who like the show Rick and Morty.

Acknowledgements I would like to thank Yehonatan Daniv for providing support to Velocity’s users on GitHub, Anand Sharma for regularly inspiring me with his motion design work, and David DeSandro for writing this book’s foreword. I’d also like to thank Mat Vogels, Harrison Shoff, Adam Singer, David Caplan, and Murat Ayfer for reviewing drafts of this book.

Contents Foreword Introduction CHAPTER 1 ADVANTAGES OF JAVASCRIPT ANIMATION

JavaScript vs. CSS animation Great performance Features Page scrolling Animation reversal Physics-based motion Maintainable workflows Wrapping up CHAPTER 2 ANIMATING WITH VELOCITY.JS

Types of JavaScript animation libraries Installing jQuery and Velocity Using Velocity: Basics Velocity and jQuery Arguments Properties Values Chaining Using Velocity: Options Duration Easing Begin and Complete Loop Delay Display and Visibility Using Velocity: Additional features Reverse Command Scrolling

Colors Transforms Using Velocity: Without jQuery (intermediate) Wrapping up CHAPTER 3 MOTION DESIGN THEORY

Motion design improves the user experience Utility Borrow conventions Preview outcomes Distraction over boredom Leverage primal instincts Make interactions visceral Reflect gravitas Reduce concurrency Reduce variety Mirror animations Limit durations Limit animations Elegance Don’t be frivolous Your one opportunity to be frivolous Consider personality Go beyond opacity Break animations into steps Stagger animations Flow from the triggering element Use graphics Wrapping up CHAPTER 4 ANIMATION WORKFLOW

CSS animation workflow Issues with CSS When CSS makes sense

Code technique: Separate styling from logic Standard approach Optimized approach Code technique: Organize sequenced animations Standard approach Optimized approach Code technique: Package your effects Standard approach Optimized approach Design techniques Timing multipliers Use Velocity Motion Designer Wrapping up CHAPTER 5 ANIMATING TEXT

The standard approach to text animation Preparing text elements for animation with Blast.js How Blast.js works Installation Option: Delimiter Option: customClass Option: generateValueClass Option: Tag Command: Reverse Transitioning text into or out of view Replacing existing text Staggering Transitioning text out of view Transitioning individual text parts Transitioning text fancifully Textual flourishes Wrapping up CHAPTER 6 SCALABLE VECTOR GRAPHICS PRIMER

Creating images through code SVG markup SVG styling Support for SVG SVG animation Passing in properties Presentational attributes Positional attributes vs. transforms Implementation example: Animated logos Wrapping up CHAPTER 7 ANIMATION PERFORMANCE

The reality of web performance Technique: Remove layout thrashing Problem Solution jQuery Element Objects Force-feeding Technique: Batch DOM additions Problem Solution Technique: Avoid affecting neighboring elements Problem Solution Technique: Reduce concurrent load Problem Solution Technique: Don’t continuously react to scroll and resize events Problem Solution Technique: Reduce image rendering Problem Solution

Sneaky images Technique: Degrade animations on older browsers Problem Solution Find your performance threshold early on Wrapping up CHAPTER 8 ANIMATION DEMO

Behavior Code structure Code section: Animation setup Code section: Circle creation Code section: Container animation 3D CSS primer Properties Options Code section: Circle animation Value functions Opacity animation Translation animation Reverse command Wrapping up Index

Foreword It’s a special time when a developer first discovers jQuery’s .animate(). I remember trying to animate any part of the page that wasn’t bolted to the main content. I created accordions, fly-out menus, hover effects, scroll transitions, magical reveals, and parallax sliders. Turning my websites from cold, static documents into moving, visual experiences felt like I was reaching another level as a web designer. But it was just bells and whistles. I realize now that for all the animation I added, I hadn’t actually improved the user experience of my websites. All the same, it was thrilling. So what makes animation so exciting? My apartment looks over downtown Brooklyn. I see people walk down the street. Plumes from smokestacks billow up. Pigeons flutter to perch on a ledge. A construction crane raises a section of a building. A single, heart-shaped balloon floats up into the Brooklyn sky (corny, I know, but I literally saw this happen twice). Cars drive over the Williamsburg Bridge. Clouds pass overhead. The world is in motion. This is how you expect the universe to work. Things move. Like the movements outside my window, each one is a one-sentence story. Together they tell the larger story of what is happening. Yet this isn’t how digital interfaces work. Those little stories are missing. When things change, you have to fill in the story for yourself. When you press the Next button at an ATM, the screen suddenly changes. Did it move forward successfully? Was there an error? You have to read the screen again to interpret the results of your action. Utilizing motion removes this leap of understanding between interactions. Motion inherently communicates what has changed. It’s like writing tiny stories between states. When a slide transition takes you to the next screen, animation helps you better understand what just happened. Wielding this power is what makes animation so thrilling. Like layout, color, and typography, animation helps you shape and direct the user experience. Animation is more than just making things move. It’s designing more effectively, and doing it thoughtfully. Unfortunately, in the history of web animation, thoughtfulness hasn’t always been the highest priority. As developers, we’ve used Flash, animated GIFs, Java applets, marquee tags, and, more recently, CSS, JavaScript, and SVG to create animation that’s been, at best, a level of polish or, at worst, a gimmick. The idea of creating animation that’s both high-performance and user-friendly is relatively new. So it’s a good thing you have this book in front of you. Julian Shapiro is one of the principal experts on animation on the web. In creating and supporting Velocity.js, he has developed an intimate knowledge of all the quirks and advantages of using motion on websites. Web Animation using JavaScript will give you not only the technical know-how required to implement animation in your websites, but, more importantly, the insights you’ll need to use animation effectively and craft compelling user experiences.

Animation libraries and technologies have made motion design more accessible than ever. But not every developer abides by best practices. The past couple of years have seen several trendy anti-patterns come and go. Scroll behavior has been hijacked. Mobile navigation has been pushed into menus accessible only via gestures. While adding animation is within the grasp of anyone who stumbles across .animate(), utilizing it to improve the user experience is one of the hallmarks of a dedicated developer. This book will help you become one of them. David DeSandro February 2015 Brooklyn, New York David DeSandro is the founder of Metafizzy and author/developer of Masonry and Isotope.

Introduction In the early days of the web, animation was primarily used by novice developers as a last-ditch effort to call attention to important parts of a page. And even if they wanted animation to transcend its niche, it couldn’t: browsers (and computers) were simply too slow to deliver smooth web-based animation. We’ve come a long way since the days of flashing banner ads, scrolling news tickers, and Flash intro videos. Today, the stunning motion design of iOS and Android dramatically improves the user experience—instead of detracting from it. Developers of the best sites and apps leverage animation to improve the feel and intuitiveness of their user interfaces. Animation’s rise to relevancy isn’t just a by-product of improved processing power; it reflects a better appreciation for best practices within the web development community. The tools you use to make a website are now considered less important than the quality of the resulting user experience. As obvious as this seems, it wasn’t always the case. So, what makes animation in particular so useful? Whether it’s transitioning between chunks of content, designing intricate loading sequences, or alerting the user what to do next, animation complements text and layout to reinforce your site’s intended behavior, personality, and visual sophistication. Does your content bounce into view in a friendly way, or does it whip across the screen? This is the domain of motion design, and the decisions you make will establish the transcendent feeling of your app. When users recommend your app to others, they’ll often try to describe it with words like “sleek” or “polished.” What they don’t realize is that they’re mostly referring to the motion design work that’s gone into the interface. This inability of the layman to make the distinction is precisely what great user interface (UI) designers strive for: animations that reinforce the interface’s objectives but don’t otherwise divert the user’s attention. This book provides you with the foundation necessary to implement animation confidently and in a way that’s both technically maintainable and visually impactful. Throughout, it considers the balance between enriching a page with motion design and avoiding unnecessary flourishes. Why is all of this so important? Why is it worth your time to perfect your transitions and easing combinations? For the same reason that designers spend hours perfecting their font and color combinations: refined products simply feel superior. They leave users whispering to themselves, “Wow, this is cool,” right before they turn to a friend and exclaim, “You gotta see this!” Note If you’re unfamiliar with basic CSS properties, you should pick up an introductory HTML and CSS book before reading this one.

Chapter 1. Advantages of JavaScript Animation In this chapter, we compare JavaScript to CSS for the purposes of animation, and introduce the unique features and workflow advantages provided by JavaScript. In short, we provide the context needed to help you understand everything you’ll learn about JavaScript in this book.

JavaScript vs. CSS animation There’s a false belief in the web development community that CSS animation is the only performant way to animate on the web. This misconception has led many developers to abandon JavaScript-based animation altogether, forcing them to Manage the entirety of user interface (UI) interaction within style sheets, which can quickly become difficult to maintain. Sacrifice real-time animation timing control, which is achievable only within JavaScript. (Timing control is necessary for designing animation into UIs that respond to a user’s drag input, like those found in mobile apps.) Forgo physics-based motion design, which allows elements on a webpage to behave like objects in the real world. Lose support for older browser versions, which remain popular throughout the world. JavaScript-based animation is actually often as fast as CSS-based animation. CSS animation is mistakenly considered to have a significant leg up because it’s most often compared to jQuery’s animation features, which are in fact very slow. However, alternative JavaScript animation libraries that bypass jQuery entirely deliver fantastic performance by streamlining their interaction with a page. Note One library of note, which we’ll be using throughout this book, is Velocity.js. It’s lightweight yet incredibly feature rich, and it mirrors jQuery’s animation syntax to help eliminate the learning curve. Of course, CSS is perfectly suited for hover state animations (turning a link blue when the mouse is positioned over it, for example), which are very often the extent to which basic webpages include animation. CSS transitions fit seamlessly into existing stylesheets, allowing developers to avoid bloating their pages with unnecessary JavaScript libraries. What’s more, CSS animation delivers blazing performance out of the box. But this book will demonstrate why JavaScript is often the superior choice for animations beyond simple hover state animations.

Great performance JavaScript and jQuery are falsely conflated. JavaScript animation is fast. jQuery slows it down. Despite jQuery being tremendously powerful, it wasn’t designed to be a highperformance animation engine. It has no mechanism to avoid “layout thrashing,” in which a browser becomes overtasked with layout processing work while it’s in the process of animating. Further, because jQuery’s code base serves many purposes beyond animation, its memory consumption triggers garbage collections within the browser, causing animations to stutter unpredictably. Lastly, due to decisions made by the jQuery team in the noble pursuit of helping novice users avoid sabotaging their UI with bad code, jQuery forgoes the recommended practice of using the requestAnimationFrame function, which browsers make available to drastically improve frame rates for web animation. JavaScript animation libraries that bypass jQuery entirely deliver fantastic performance by streamlining their interaction with a page. One library of note, which we’ll be using throughout this book, is Velocity.js. It’s lightweight, yet incredibly feature rich, and it mirrors jQuery’s animation syntax to help eliminate the learning curve. This is a topic we’ll explore in-depth in Chapter 7, “Animation Performance.” By learning the nuances of browser rendering performance, you’ll gain a foundation on which to build reliable animations for all browsers and devices, regardless of their individual processing power.

Features Speed is, of course, not the only reason to use JavaScript—its abundance of features is equally as important. Let’s run through a few of the notable animation features that are exclusive to JavaScript.

Page scrolling Page scrolling is one of the most popular uses for JavaScript-based animation. A recent trend in web design is to create long webpages that animate new pieces of content into view as the page is scrolled down. JavaScript animation libraries, such as Velocity, provide simple functions for scrolling elements into view: Click here to view code image $element.velocity(“scroll”, 1000);

This scrolls the browser toward the top edge of $element over a duration of 1000ms using Velocity’s "scroll" command. Notice that Velocity’s syntax is nearly identical to jQuery’s $.animate() function, which is covered later in this chapter.

Animation reversal Animation reversal is a useful shorthand for undoing an element’s previous animation. By invoking the reverse command, you’re instructing an element to animate back to its values prior to its last animation. A common use for reversal is animating a modal dialogue into view, then hiding it when the user presses to close it. An unoptimized reversal workflow consists of keeping track of the specific properties that were last animated on each element that may later be subjected to reversal. Unfortunately, keeping track of prior animation states in UI code quickly becomes unwieldy. In contrast, with the reverse command, Velocity remembers everything for you. Mimicking the syntax of Velocity’s scroll command, the reverse command is called by passing "reverse" as Velocity’s first argument: Click here to view code image // First animation: Animate an element’s opacity toward 0 $element.velocity({ opacity: 0 }); // Second animation: Animate back toward the starting opacity value of 1 $element.velocity(“reverse”);

When it comes to JavaScript’s animation timing control, there’s more than just reversal: JavaScript also allows you to globally slow down or speed up all JavaScript animations currently running. You’ll learn more about this powerful feature in Chapter 4, “Animation Workflow.”

Physics-based motion The utility of physics in motion design reflects the core principle of what makes for a great user experience (UX) on your site: interfaces that flow naturally from the user’s input. Put another way, interfaces that pay tribute to how objects move in the real world. As a simple yet powerful introduction to physics-based motion Velocity offers an easing type based on spring physics. (We’ll fully explore the concept of easing in the next chapter.) With typical easing options, you pass in a string corresponding to a predefined easing curve (for example, "ease" or "easeInOutSine"). The spring physics easing type, in contrast, accepts a two-item array. Click here to view code image // Animate an element’s width to “500px” using a spring physics easing of 500 tensions units and 20 friction units $element.velocity({ width: “500px” }, { easing: [ 500, 20 ] });

The first item in the easing array represents the tension of the simulated spring and the second item represents friction. A higher tension value increases the total speed and bounciness of the animation. A lower friction value increases the vibration speed at the tail end of the animation. By tweaking these values, you can give each animation on your page a unique movement profile, which helps to reinforce the differentiation between their individual behaviors.

Maintainable workflows Designing animation is an experimental process that requires repeated tweaking of timing and easing values to achieve a uniform feel across the page. Inevitably, just when you’ve perfected your design, a client will request significant changes. In these situations, maintainable code becomes critical. The JavaScript-based solution to this workflow problem is wonderfully elegant, and it’s covered in depth in Chapter 4, “Animation Workflow.” For now, here’s the short explanation: There are techniques for chaining together individual JavaScript animations —all with differing durations, easings, and so on—such that the timing of one animation does not affect another. This means you can change individual durations without redoing math and you can go back and easily set animations to run either in parallel or consecutively.

Wrapping up When designing animations in CSS, you’re inherently limited to the features that the CSS specification provides. In JavaScript, because of the very nature of programming languages, third-party libraries have an infinite amount of logical control over motion design. Animation engines leverage this to provide powerful features that drastically improve workflow and expand the possibilities of interactive motion design. That’s what this book is all about: Designing beautiful animations as efficiently as possible. The next chapter explains how to use this book’s JavaScript animation engine of choice: Velocity.js. In mastering Velocity.js, you’ll understand how to leverage the features we’ve just introduced, and many more.

Chapter 2. Animating with Velocity.js In this chapter, you’ll learn the features, commands, and options provided by Velocity.js. If you’re familiar with jQuery-based animation, you already know how to use Velocity; it functions nearly identically to jQuery’s $.animate() function. But regardless of your existing knowledge, the methodical feature breakdowns in this chapter will introduce you to the nuances of animation engine behavior. Mastering these nuances will help take you from novice to professional. Even if you’re already intimately familiar with JavaScript animation and Velocity.js, do yourself a favor and skim this chapter. You’re bound to discover something you didn’t realize you could do.

Types of JavaScript animation libraries There are many types of JavaScript animation libraries. Some replicate physics interactions in the browser. Some make WebGL and Canvas animations easier to maintain. Some focus on SVG animation. Some improve UI animation—this last type is the focus of this book. The two popular UI animation libraries are GSAP (download it at GreenSock.com) and Velocity (download it at VelocityJS.org). You’ll work with Velocity throughout this book since it’s free under the MIT license (GSAP requires licensing fees depending on a site’s business model), plus it boasts incredibly powerful features for writing clean and expressive animation code. It’s in use on many popular sites, including Tumblr, Gap, and Scribd. Oh, and it was created by the author of this book!

Installing jQuery and Velocity You can download jQuery from jQuery.com, and Velocity from VelocityJS.org. To use them on your page—as with any JavaScript library—simply include tags pointing toward the respective libraries before your page’s tag. If you’re linking to pre-hosted versions of the libraries (as opposed to local copies on your computer), your code might look like this: Click here to view code image

My Page My content.

When using jQuery and Velocity together, include jQuery before Velocity. That’s it! Now you’re ready to roll.

Using Velocity: Basics To get oriented to Velocity, we’ll start with the basic components: arguments, properties, values, and chaining. Since jQuery is so ubiquitous, it is also important to look at the relationship between Velocity and jQuery.

Velocity and jQuery Velocity functions independently of jQuery, but the two can be used in combination. It’s often preferable to do so to benefit from jQuery’s chaining capabilities: When you’ve preselected an element using jQuery, you can extend it with a call to .velocity() to animate it: Click here to view code image // Assign a variable to a jQuery element object var $div = $(“div”); // Animate the element using Velocity $div.velocity({ opacity: 0 }); This syntax is identical to jQuery’s own animate function: $div.animate({ opacity: 0 });

All the examples in this book use Velocity in combination with jQuery, and therefore follow this syntax.

Arguments Velocity accepts multiple arguments. Its first argument is an object that maps CSS properties to their desired final values. The properties and their accepted value types correspond directly to those used in CSS (if you’re unfamiliar with basic CSS properties, pick up an introductory HTML and CSS book before reading this one): Click here to view code image // Animate an element to a width of “500px” and to an opacity of 1. $element.velocity({ width: “500px”, opacity: 1 });

Tip In JavaScript, if you’re providing a property value that contains letters (instead of only integers), put the value in quotes. You can pass in an object specifying animation options as a second argument: Click here to view code image $element.velocity({ width: “500px”, opacity: 1 }, { duration: 400, easing: “swing” });

There’s also a shorthand argument syntax: Instead of passing in an options object as a second argument, you can use comma-separated argument syntax. This entails listing values for duration (which accepts an integer value), easing (a string value), and complete (a function value) in any comma-separated order. (You’ll learn what all of these options do momentarily.)

Click here to view code image // Animate with a duration of 1000ms (and implicitly use the default easing value of “swing”) $element.velocity({ top: 50 }, 1000); // Animate with a duration of 1000ms and an easing of “ease-in-out” $element.velocity({ top: 50 }, 1000, “ease-in-out”); // Animate with an easing of “ease-out” (and implicitly use the default duration value of 400ms) $element.velocity({ top: 50 }, “ease-out”); // Animate with a duration of 1000ms and a callback function to be triggered upon animation completion $element.velocity({ top: 50 }, 1000, function() { alert(“Complete.”) });

This shorthand syntax is a quick way of passing in animation options when you only need to specify the basic options (duration, easing, and complete). If you pass in an animation option other than these three, you must switch all options to the object syntax. Hence, if you want to specify a delay option, change the following syntax: Click here to view code image $element.velocity({ top: 50 }, 1000, “ease-in-out”);

to this syntax: Click here to view code image // Re-specify the animation options used above, but include a delay value of 500ms $element.velocity({ top: 50 }, { duration: 1000, easing: “ease-in-out”, delay: 500 });

You can’t do this: Click here to view code image // Incorrect: Divides animation options between the comma-separated syntax and the object syntax $element.velocity({ top: 50 }, 1000, { easing: “ease-in-out”, delay: 500 });

Properties There are two differences between CSS-based and JavaScript-based property animation. First, unlike in CSS, Velocity accepts only a single numeric value per CSS property. So, you can pass in: Click here to view code image $element.velocity({ padding: 10 });

or Click here to view code image $element.velocity({ paddingLeft: 10, paddingRight: 10 });

But you can’t pass in: Click here to view code image // Incorrect: The CSS property is being passed more than one numeric value. $element.velocity({ padding: “10 10 10 10” });

If you do want to animate all four padding values (top, right, bottom, and left),

list them out as separate properties: // Correct $element.velocity({ paddingTop: 10, paddingRight: 10, paddingBottom: 10, paddingLeft: 10 });

Other common CSS properties that can take multiple numeric values include margin, transform, text-shadow, and box-shadow. Breaking up compound properties into their sub-properties for the purposes of animation gives you increased control over easing values. In CSS, you can specify only one property-wide easing type when animating multiple sub-properties within the parent padding property, for example. In JavaScript, you can specify independent easing values for each sub-property—the advantages of this will become apparent during the discussion of CSS transform property animation later in this chapter. Listing out independent sub-properties can also make your animation code easier to read and easier to maintain. The second difference between CSS-based and JavaScript-based property animation is that JavaScript properties drop the dashes between words and all words past the first must be capitalized. For example, padding-left becomes paddingLeft, and background-color becomes backgroundColor. Further note that JavaScript property names should not be in quotes: Click here to view code image // Correct $element.velocity({ paddingLeft: 10 }); // Incorrect: Uses a dash and doesn’t capitalize $element.velocity({ padding-left: 10 }); // Incorrect: Uses quotes around the JavaScript-formatted property name $element.velocity({ “paddingLeft”: 10 });

Values Velocity supports the px, em, rem, %, deg, vw, and vh units. If you don’t provide a unit type with a numeric value, an appropriate one is automatically assigned based on the CSS property type. For most properties, px is the default unit, but a property that expects a rotation angle, such as rotateZ for example, would be automatically assigned the deg (degree) unit: Click here to view code image $element.velocity({ top: 50, // Defaults to the px unit type left: “50%”, // We manually specify the % unit type rotateZ: 25 // Defaults to the deg unit type });

Explicitly declaring unit types for all property values increases your code’s legibility by making the contrast between the px unit and its alternatives more obvious when quickly

eyeballing your code. Another advantage of Velocity over CSS is that it supports four value operators that can be optionally prefixed to a property value: +, -, *, and /. These directly correspond to their math operators in JavaScript. You can combine these value operators with an equals sign (=) to perform relative math operations. Refer to the inline code comments for examples: Click here to view code image $element.velocity({ top: “50px”, // No operator. Animate toward 50 as expected. left: “-50”, // Negative operator. Animate toward -50 as expected. width: “+=5rem”, // Convert the current width value into its rem equivalent and add 5 more units. height: “-10rem”, // Convert the current height value into its rem equivalent and subtract 10 units. paddingLeft: “*=2” // Double the current paddingLeft value. paddingRight: “/=2” // Divide the current paddingLeft value into two. });

Velocity’s shorthand features, such as value operators, retain animation logic entirely within the animation engine. This not only keeps the code more concise by eliminating manual value calculation, but also improves performance by telling Velocity more about how you plan to animate your elements. The more logic that is performed within Velocity, the better Velocity can optimize your code for higher frame rates.

Chaining When multiple Velocity calls are chained back-to-back on an element (or a series of elements), they automatically queue onto one another. This means that each animation begins once the preceding animation has completed: Click here to view code image $element // Animate the width and height properties .velocity({ width: “100px”, height: “100px” }) // When width and height are done animating, animate the top property .velocity({ top: “50px” });

Using Velocity: Options To round out this introduction to Velocity, let’s run through the most commonly used options: duration, easing, begin and complete, loop, delay, and display.

Duration You can specify the duration option, which dictates how long an animation call takes to complete, in milliseconds (1/1000th of a second) or as one of three shorthand durations: "slow" (equivalent to 600ms), "normal" (400ms), or "fast" (200ms). When specifying a duration value in milliseconds, provide an integer value without any unit type: Click here to view code image

// Animate with a duration of 1000ms (1 second) $element.velocity({ opacity: 1 }, { duration: 1000 });

or Click here to view code image $element.velocity({ opacity: 1}, { duration: “slow” });

The advantage to using the named shorthand durations is that they express the tempo of an animation (is it slow or is it fast?) when you’re reviewing your code. If you use these shorthands exclusively, they’ll also naturally lead to more uniform motion design across your site, since all of your animations will fall into one of three speed categories instead of each being passed an arbitrary value.

Easing Easings are the mathematical functions that define how fast or slow animations occur in different parts of an animation’s total duration. For example, an easing type of "easein-out" indicates that the animation should gradually accelerate (ease in) during the first part then gradually decelerate (ease out) during the final part. In contrast, an easing type of "ease-in" produces an animation that accelerates up to a target speed during the first part of an animation but thereafter remains at a constant speed until the animation completes. An easing type of "ease-out" is the converse of this: the animation starts and continues at a constant speed before it gradually decelerates during the final part of the animation. Much like the physics-based motion discussed in Chapter 1, “Advantages of JavaScript Animation,” easings give you the power to inject personality into your animations. Take, for example, how robotic an animation that uses the linear easing feels. (A linear easing produces an animation that starts, runs, and ends at the same velocity.) The robotic feel is the result of an association with linear robotic motion in the real world: Self-guided mechanical objects typically move in straight lines and operate at constant speeds because there’s neither an aesthetic nor an organic reason for them to do otherwise. In contrast, living things—whether it’s the human body or trees blowing in the wind— never move at constant speed in the real world. Friction and other external forces cause them to move at varying speeds. Great motion designers pay homage to organic motion because it gives the impression that the interface is responding fluidly to the user’s interaction. In mobile apps, for example, you expect a menu to quickly accelerate away from your fingers when you swipe it off-screen. If the menu were to instead move away from your fingers at a constant speed —like a robotic arm—you’d feel as if the swipe merely set off a chain of motion events that were outside your control. You’ll learn more about the power of easing types in Chapter 3, “Motion Design Theory.” For now, let’s run through all of Velocity’s available easing values: jQuery UI’s trigonometric easings. For a complete listing of these easing equations, as well as interactive demonstrations of their acceleration profiles, refer to the demos on easings.net.

Click here to view code image $element.velocity({ width: “100px” }, “easeInOutSine”);

CSS’s easings: "ease-in", "ease-out", "ease-in-out", and "ease" (a subtler version of "ease-in-out"). Click here to view code image $element.velocity({ width: “100px” }, “ease-in-out”);

CSS’s Bézier curves: The Bézier curve easing allows complete control over the structure of an easing’s acceleration curve. A Bézier curve is defined by specifying the height of four equidistant points on a chart, which Velocity accepts in the format of a four-item array of decimal values. Visit cubic-bezier.com for an interactive guide to creating Bézier curves. Click here to view code image $element.velocity({ width: “100px” }, [ 0.17, 0.67, 0.83, 0.67 ]);

Spring physics: This easing type mimics the bouncy behavior of a spring that’s been stretched then suddenly released. As with the classical physics equation that defines the motion of a spring, this easing type lets you pass in a two-item array in the form of [ tension, friction ]. A higher tension (default: 500) increases total speed and bounciness. A lower friction (default: 20) increases ending vibration speed. Click here to view code image $element.velocity({ width: “100px” }, [ 250, 15 ]);

"spring" easing is a predefined implementation of the spring physics easing that’s handy to use when you don’t want to experiment with tension and friction values. Click here to view code image $element.velocity({ width: “100px” }, “spring”);

Remember that you can also pass in the easing option as an explicitly defined property in an options object argument: Click here to view code image $element.velocity({ width: 50 }, { easing: “spring” });

Do not be overwhelmed by the number of easing options available to you. You’ll most often rely on the CSS easing types and the “spring” easing, which suit the vast majority of animation use cases. The most complex easing type, the Bézier curve, is most often employed by developers who have a highly specific easing style in mind and aren’t afraid to get their hands dirty. Note The rest of the Velocity options in this section must be explicitly passed into an options object. Unlike those already described, these additional options cannot be supplied to Velocity in the shorthand comma-separated syntax.

Begin and Complete The begin and complete options allow you to specify functions to be triggered at certain points in an animation: Pass the begin option a function to be called prior to the start of an animation. Conversely, pass the complete option a function to be called at the completion of an animation. With both options, the function is called once per animation call, even if multiple elements are being animated at once: Click here to view code image var $divs = $(“div”); $divs.velocity( { opacity: 0 }, // Open an alert box right before the animation begins { begin: function () { console.log(“Begin!”); }, // Open an alert box once the animation completes complete: function () { console.log(“Complete!”); } } );

Callback Functions These options are commonly referred to as “callback functions” (or “callbacks”) since they are “called” when certain events occur in the future. Callbacks are useful for firing events that are dependent on the visibility of elements. For example, if an element starts at invisible then animates toward an opacity of 1, it may be appropriate to subsequently trigger a UI event that modifies the new content once users are able to see it. Remember that you don’t need to use callbacks to queue animations onto one another; animations automatically fire sequentially when more than one is assigned to a single element or set of elements. Callbacks are for the queuing of nonanimation logic.

Loop Set the loop option to an integer to specify the number of times an animation should alternate between the values in the call’s property map and the element’s values prior to the call: Click here to view code image $element.velocity({ height: “10em” }, { loop: 2 });

If the element’s original height was 5em, its height would alternate between 5em and 10em twice. If the begin or complete options are used with a looped call, they are triggered once each—at the very beginning and end of the total loop sequence, respectively; they are not retriggered for each loop alternation. Instead of passing in an integer, you can also pass in true to trigger infinite looping:

Click here to view code image $element.velocity({ height: “10em” }, { loop: true });

Infinite loops ignore the complete callback since they don’t naturally end. They can, however, be manually stopped via Velocity’s stop command: $element.velocity(“stop”);

Non-infinite loops are useful for animation sequences that would otherwise require the repetition of chained animation code. For example, if you were to bounce an element up and down twice (perhaps to alert the user of a new message awaiting them), the nonoptimized code would look like this: Click here to view code image $element // Assume translateY starts at “0px” .velocity({ translateY: “100px” }) .velocity({ translateY: “0px” }) .velocity({ translateY: “100px” }) .velocity({ translateY: “0px” });

The more compact and easier to maintain version of this code would look like this: Click here to view code image // Repeat (loop) this animation twice $element.velocity({ translateY: “100px” }, { loop: 2 });

With this optimized version, if you have a change of heart about how much the top value should be changed by (currently "100px"), you need only change the top value in one part of the code. If there are many such instances of repetition in your code, it quickly becomes obvious how much looping benefits your workflow. Infinite looping is tremendously helpful for loading indicators, which typically animate indefinitely until none" or "block", then you’d proceed to alternate the value as appropriate. The process of checking for the display property constitutes a get, and whichever action is subsequently taken to show or hide the side menu will constitute a set. The optimized implementation of this code would entail maintaining a variable in memory that’s updated whenever the button is clicked, and checking that variable for the side menu’s current status before toggling its visibility. In this way, the get can be skipped altogether, which helps reduce the likelihood of the code producing a set alternated with a get. Further, beyond reducing the likelihood of layout thrashing, the UI now also benefits from having one less page query. Keep in mind that each set and get is a relatively expensive browser operation; the fewer there are, the faster your UI will perform. Many tiny improvements ultimately add up to a substantial benefit, which is the underlying theme of this chapter: Follow as many performance best practices as you can, and you’ll wind up with a UI that rarely sacrifices your desired motion design goals for the sake of performance.

jQuery Element Objects Instantiating jQuery element objects (JEO) is the most common culprit of DOM gets. You may be wondering what a JEO is, but you’ve certainly seen this code snippet before: Click here to view code image $(“#element”).css(“opacity”, 1); … or its raw JavaScript equivalent: document.getElementById(“element”).style.opacity = 1;

In the case of the jQuery implementation, the value returned by $("#element") is a JEO, which is an object that wraps the raw DOM element that was queried. JEO’s provide you with access to all of your beloved jQuery functions, including .css(), .animate(), and so on. In the case of the raw JavaScript implementation, the value returned by getElementByid("element") is the raw (unwrapped) DOM element. In both

implementations, the browser is instructed to search through the DOM tree to find the desired element. This is an operation that, when repeated in bulk, impacts page performance. This performance concern is exacerbated when uncached elements are used in code snippets that are repeated, such as the code contained by a loop. Consider the following example: Click here to view code image $elements.each(function(i, element) { $(“body”).append(element); });

You can see how $("body") is a JEO instantiation that’s repeated for every iteration of the $.each() loop: In addition to appending the loop’s current element to the DOM (which has its own performance implications), you’re now also repeatedly forcing a DOM query. Seemingly harmless one-line operations like these add up very quickly. The solution here is to cache the results—or, save the returned JEO’s into variables—to avoid a repeated DOM operation every time you want to call a jQuery function on an element. Hence, the code goes from looking like this: Click here to view code image // Bad practice: We haven’t cached our JEO $(“#element”).css(“opacity”, 1); // … some intermediary code… // We instantiate the JEO again $(“#element”).css(“opacity”, 0);

to looking like this after it’s properly optimized: Click here to view code image // Cache the jQuery element object, prefixing the variable with $ to indicate a JEO var $element = $(“#element”); $element.css(“opacity”, 1); // … some intermediary code… // We re-use the cached JEO and avoid a DOM query $element.css(“opacity”, 0);

Now you can reuse $element throughout your code without ever incurring a repeated DOM lookup on its behalf.

Force-feeding Traditionally, animation engines query the DOM at the start of an animation to determine the initial value of each CSS property being animated. Velocity offers a workaround to this page-querying event through a feature called force-feeding. It’s an alternative technique for avoiding layout thrashing. With force-feeding, you explicitly define your animations’ start values so that these upfront gets are eliminated. Force-fed start values are passed in as the second item in an array that takes the place of a property’s value in an animation properties map. The first item in the array is the standard end value that you’re animating toward.

Consider the following two animation examples, both of which are triggered upon page load: Click here to view code image // Animate translateX to 500px from a start value of 0 $element.velocity({ translateX: [ 500, 0 ] }); // Animate opacity to 0 from a start value of 1 $element.velocity({ opacity: [ 0, 1 ]);

In the first example, you’re passing translateX a force-fed start value of 0 since you know that the element has yet to be translated (since the page has just loaded). You’re force-feeding in what you know (or want) the original property value to be. Further, in the second example, the element’s current opacity is 1 because that’s the default value for opacity and you haven’t yet modified the element in any way. In short, with forcefeeding, you can reduce the browser’s workload in situations where you have an understanding of how elements are already styled. Note Force-feed animation properties only when they’re first used in an animation chain, not when they occur subsequently in the chain, since Velocity already does internal caching there: Click here to view code image $element // Optionally forcefeed here .velocity({ translateX:[ 500, 0 ] }) // Do not forcefeed here;500 is internally cached .velocity({ translateX:1000 });

Force-feeding is an invaluable feature for high-stress situations such as animating a large number of elements at once on a desktop browser or when dealing with low-powered mobile devices for which every page interaction incurs a noticeable delay. However, for most real-world UI animation situations, force-feeding is an unnecessary optimization that makes your code less maintainable due to having to update the force-fed start values whenever you change the elements’ values within CSS stylesheets. Note Refer to Chapter 8, “Animation Demo,” to walk through an application of force-feeding.

Technique: Batch DOM additions Like reducing layout thrashing, batching DOM additions is another performance technique to help avoid unoptimized interaction with the browser.

Problem You’re not done with gets and sets just yet! A common page set is the insertion of new DOM elements at run-time. While there are many uses for adding new elements to a page, perhaps the most popular is infinite scrolling, which consists of elements continuously animating into view at the bottom of a page while the user scrolls downward. As you learned in the previous section, browsers have to compute the composition of all affected elements whenever a new element is added. This is a relatively slow process. Hence, when DOM insertion is performed many times per second, the page is hit with a significant performance impact. Fortunately, when processing multiple elements, browsers can optimize page set performance if all elements are inserted at the same time. Unfortunately, we as developers often unintentionally forgo this optimization by separating our DOM insertions. Consider the following example of unoptimized DOM insertion code: Click here to view code image // Bad practice var $body = $(“body”); var $newElements = [ “Div 1”, “Div 2”, “Div 3” ]; $newElements.each(function(i, element) { $(element).appendTo($body); // Other arbitrary code });

This iterates through a set of element strings that are instantiated into jQuery element objects (without a performance drawback since you’re not querying the DOM for each JEO). Each element is then inserted into the page using jQuery’s appendTo(). Here’s the problem: even if additional code exists after the appendTo() statement, the browser won’t compress these DOM sets into a single insertion operation because it can’t be certain that asynchronous code operating outside the loop won’t alter the DOM’s state between insertions. For example, imagine if you queried the DOM to find out how many elements exist on the page after each insertion: Click here to view code image // Bad practice $newElements.each(function(i, element) { $(element).appendTo($body); // Output how many children the body element has console.log($body.children().size()); });

The browser couldn’t possibly optimize the DOM insertions into a single operation because the code explicitly asks the browser to tell us the accurate number of elements that exist before the next loop begins. For the browser to return the correct count each time, it can’t have batched all insertions upfront. In conclusion, when you perform DOM element insertion inside a loop, each insertion happens independently of any others, resulting in a notable performance sacrifice.

Solution Instead of individually inserting new elements into the DOM, construct the full DOM element set in memory, then insert it via a single call to appendTo(). The optimized version of the code shown in the section above now looks like this: Click here to view code image // Optimized var $body = $(“body”); var $newElements = [ “Div 1”, “Div 2”, “Div 3” ]; var html = ””; $newElements.each(function(i, element) { html += element; }); $(html).appendTo($body);

This concatenates the string representation of each HTML element onto a master string that is then turned into a JEO and appended into the DOM in a single shot. In this way, the browser is given explicit instruction to insert everything at once, and it optimizes for performance accordingly. Simple, right? As you’ll see in the remainder of this chapter, performance best practices are usually as easy as this. You simply have to train your eye to know when to use them.

Technique: Avoid affecting neighboring elements It’s important to consider the impact of an element’s animation on neighboring elements.

Problem When an element’s dimensions are animated, the changes often affect the positioning of nearby elements. For example, if an element between two sibling elements shrinks in width, the siblings’ absolute positions will dynamically change so they remain next to the animating element. Another example might be animating a child element nested inside a parent element that doesn’t have explicitly defined width and height properties. Accordingly, when the child is being animated, the parent will also resize itself so that it continues to fully wrap itself around the child. In effect, the child element is no longer the only element being animated—the parent’s dimensions are also being animated, and that’s even more work for the browser to perform upon each tick in an animation loop! There are many CSS properties whose modification can result in dimensional and positional adjustments to neighboring elements, including top, right, bottom, and left; all margin and padding properties; border thickness; and the width and height dimensions. As a performance-minded developer, you need to appreciate the impact that animating these properties can have on your page. Always ask yourself how each property you’re attempting to animate affects nearby elements. If there’s a way to rewrite your code such that you can isolate elements’ changes from one another, then consider doing so. In fact, there is an easy way to do just this—on to the solution!

Solution The simple solution to avoid affecting neighboring elements is to animate the CSS transform properties (translateX, translateY, scaleX, scaleY, rotateZ, rotateX, and rotateY) whenever possible. The transform properties are unique in that they elevate targeted elements to isolated layers that are rendered separately from the rest of the page (with a performance boost courtesy of your GPU), so that neighboring elements aren’t affected. For example, when animating an element’s translateX to a value of “500px", the element will move 500px rightward while superimposing itself on top of whatever elements exist along its animation path. If there are no elements along its path (that is, if there are no nearby elements for it to affect), then using translateX will have the same net effect on the look of your page as if you had animated using the much slower left property. Hence, whenever possible, an animation that once looked like this: Click here to view code image // Move the element 500px from the left $element.velocity({ left: “500px” });

should be refactored into this: Click here to view code image // Faster: Use translateX

$element.velocity({ translateX: “500px” });

Similarly, if you can substitute translateY for top, do so: Click here to view code image $element.velocity({ top: “100px” }); // Faster: Use translateY $element.velocity({ translateY: “100px” });

Note Sometimes you actually intend to use left or top so that neighboring elements’ positions are changed. In all other cases, get into the habit of using the transform properties. The performance impact is significant. Consider Opacity Over Color opacity is another CSS property that receives a GPU rendering boost since it doesn’t affect the positioning of elements. So, if there are elements on your page for which you’re currently animating, say, color when the user hovers over them, consider animating opacity instead. If the net effect looks almost as good as the color animation, then consider sticking with it—you’ve just boosted the UI’s performance without compromising its look. As a performance-minded developer, you’re no longer allowed to arbitrarily select animation properties. You must now consider the impact of each of your property choices. Note Refer to CSSTriggers.com for a breakdown of how CSS properties affect browser performance.

Technique: Reduce concurrent load Browsers have bottlenecks. Find out what they are and stay below them.

Problem When a page first loads, the browser processes HTML, CSS, JavaScript, and images as quickly as possible. It should come as no surprise that animations occurring during this time tend to be laggy—they’re fighting for the browser’s limited resources. So, despite the fact that a page’s loading sequence is often a great time to flaunt all your motion design skills, it’s best to restrain yourself if you want to avoid giving users the first impression that your site is laggy. A similar concurrency bottleneck arises when many animations occur at once on a page —regardless of where they take place in the page’s lifecycle. In these situations, browsers can choke under the stress of processing many styling changes at once, and stuttering can occur.

Fortunately, there are some clever techniques for reducing concurrent animation load.

Solution There are two approaches for addressing the concurrency issue: staggering and breaking up animations into sequences. Stagger One way to reduce concurrent animation load is to make use of Velocity’s UI pack’s stagger feature, which delays the start times of successive animations in a set of elements by a specified duration. For example, to animate every element in a set toward an opacity value of 1 with successive 300ms delays between start times, your code might look like this: Click here to view code image $elements.velocity({ opacity: 1 }, { stagger: 300 });

The elements are no longer animating in perfect synchronization; instead, at the very start of the entire animation sequence, only the first element is animating. Later, at the very end of the entire sequence, only the last element is animating. You’re effectively spreading out the animation sequence’s total workload so that the browser is always performing less work at one time than it would have had it been animating every element simultaneously. What’s more, implementing staggering into your motion design is often a good aesthetic choice. (Chapter 3, “Motion Design Theory,” further explores the merits of staggering.) Multi-animation sequences There’s one more clever way to reduce concurrent load: break up property animations into multi-animation sequences. Take, for example, the case of animating an element’s opacity value. This is typically a relatively low-stress operation. But, if you were to simultaneously animate the element’s width and box-shadow properties, you’d be giving the browser appreciably more work to perform: more pixels will be affected, and more computation would be required. Hence, an animation that looks like this: Click here to view code image $images.velocity({ opacity: 1, boxShadowBlur: “50px” });

might be refactored into this: Click here to view code image $images .velocity({ opacity: 1 }) .velocity({ boxShadowBlur: “50px” });

The browser has less concurrent work to do since these individual property animations occur one after another. Note that the creative tradeoff being made here is that we’ve opted to prolong the total animation sequence duration, which may or may not be desirable for your particular use case.

Since an optimization such as this entails changing the intention of your motion design, this is not a technique that should always be employed. Consider it a last resort. If you need to squeeze additional performance out of low-powered devices, then this technique may be suitable. Otherwise, don’t pre-optimize the code on your site using techniques like this, or you’ll end up with unnecessarily bloated and inexpressive code.

Technique: Don’t continuously react to scroll and resize events Be mindful of how often your code is being run. A fast snippet of code being run 1,000 times per second may—in aggregate—no longer be very fast.

Problem Browsers’ scroll and resize events are two event types that are triggered at very high rates: when a user resizes or scrolls the browser window, the browser fires the callback functions associated with these events many times per second. Hence, if you’ve registered callbacks that interact with the DOM—or worse, contain layout thrashing—they can cause tremendously high browser load during times of scrolling and resizing. Consider the following code: Click here to view code image // Perform an action when the browser window is scrolled $(window).scroll(function() { // Anything in here is fired multiple times per second while the user scrolls }); // Perform an action when the browser window is resized $(window).resize(function() { // Anything in here is fired multiple times per second while the user resizes });

Recognize that the functions above aren’t simply called once when their respective events start; instead, they are called throughout the duration of the user’s respective interaction with the page.

Solution The solution to this problem is to debounce event handlers. Debouncing is the process of defining an interval during which an event handler callback will be called only once. For example, say you defined a debounce interval of 250ms and the user scrolled the page for a total duration of 1000ms. The debounced event handler code would accordingly fire only four times (1000ms/250ms). The code for a debounce implementation is beyond the scope of this book. Fortunately, many libraries exist exclusively to solve this problem. Visit davidwalsh.name/javascriptdebounce-function for one example. Further, the tremendously popular Underscore.js (UnderscoreJS.org), a JavaScript library akin to jQuery that provides helper functions for making coding easier, includes a debounce function that you can easily reuse across your event handlers.

Note As of this book’s writing, the latest version of Chrome automatically debounces scroll events.

Technique: Reduce image rendering Not all elements are rendered equally. Browsers have to work overtime when displaying certain elements. Let’s look at which those are.

Problem Videos and images are multimedia element types that browsers have to work extra hard to render. Whereas the dimensional properties of non-multimedia HTML elements can be computed with ease, multimedia elements contain thousands of pixel-by-pixel data points that are computationally expensive for browsers to resize, reposition, and recomposite. Animating these elements will always be less less than optimal versus animating standard HTML elements such as div, p, and table. Further, given that scrolling a page is nearly equivalent to animating a page (think of scrolling as animating the page’s top property), multimedia elements can also drastically reduce scrolling performance on CPU-constrained mobile devices.

Solution Unfortunately, there’s no way to “refactor” multimedia content into faster element types, other than turning simple, shape-based images into SVG elements wherever possible. Accordingly, the only available performance optimization is reducing the total number of multimedia elements that are displayed on the page at once and animated at once. Note that the words at once stress a reality of browser rendering: browsers only render what’s visible. The portions of your page (including the portions that contain additional images) that aren’t visible do not get rendered, and do not impose additional stress on browser processes. So, there are two best practices to follow. First, if you’re ever on the fence about adding an additional image to your page, opt to not include it. The fewer images there are to render, the better UI performance will be. (Not to mention the positive impact fewer images will have on your page’s network load time.) Second, if your UI is loading many images into view at once (say, eight or more, depending on your device’s hardware capabilities), consider not animating the images at all, and instead crudely toggling the visibility of each image from invisible to visible. To help counteract how inelegant this can look, consider staggering visibility toggling so that the images load into view one after another instead of simultaneously. This will help guide the user’s eye across the loading sequence, and will generally deliver more refined motion design.

Note Refer to Chapter 3, “Motion Design Theory,” to learn more about animation design best practices.

Sneaky images You’re not done yet. There’s more to this section than meets the eye, as we haven’t fully explored the ways in which images can materialize on a page. The obvious culprit is the img element, but there are two other ways that images can sneak onto your pages. CSS gradients These are actually a type of image. Instead of being pre-produced by a photo editor, they are produced at run-time according to CSS styling definitions, for example, using a linear-gradient() as the background-image value on an element. The solution here is to opt for solid-color backgrounds instead of gradients whenever possible. Browsers can easily optimize the rendering of solid chunks of color, but, as with images, they have to work overtime to render gradients, which differ in color from pixel to pixel. Shadow properties The evil twin siblings of gradients are the box-shadow and text-shadow CSS properties. These are rendered similarly to gradients, but instead of stylizing background-color, they effectively stylize border-color. What’s worse, they have opacity falloffs that require browsers to perform extra compositing work because the semitransparent portions of the gradients must be rendered against the elements underneath the animating element. The solution here is similar to the previous one: if your UI looks almost as good when you remove these CSS properties from your stylesheet, pat yourself on the back and never look back. Your website’s performance will thank you. These recommendations are simply that: recommendations. They are not performance best practices since they sacrifice your design intentions for increased performance. Considered them only as last resorts when your site’s performance is poor and you’ve exhausted all other options.

Technique: Degrade animations on older browsers You don’t have to neglect supporting underperforming browsers and devices. If you embrace a performance-minded workflow from day one, you can simply provide them with a degraded—but completely functional—experience.

Problem Internet Explorer 8—a slow, outdated browser—is dying in popularity. But Internet Explorer 9, its successor, is still widely used outside of the Americas. Further, older Android smartphones running Android 2.3.x and below, which are slow relative to the latest-generation Android and iOS devices, also remain tremendously popular. Out of every ten users to your site, expect up to three of them to fall into one of these two groups (depending on the type of users your app attracts). Accordingly, if your site is rich in animation and other UI interactions, assume it will perform especially poorly for up to a third of your users.

Solution There are two approaches to addressing the performance issue raised by weaker devices: either broadly reduce the occurrence of animations across your entire site, or reduce them exclusively for the weaker devices. The former is a ultimately a product decision, but the latter is a simple technical decision that is easily implemented if you’re using the global animation multiplier technique (or Velocity’s equivalent mock feature) explained in the Chapter 4, “Animation Workflow.” The global multiplier technique lets you dynamically alter the timing of animations across your entire site by setting a single variable. The trick then—whenever a weak browser is detected—is to set the multiplier to 0 (or set $.Velocity.mock to true) so that all of a page’s animations complete within a single animation tick (less than 16ms): Click here to view code image // Cause all animations to complete immediately $.Velocity.mock = true;

The result of this technique is that weaker devices experience UI animations that degrade so that instant style changes replace your animated transition. The benefits are significant: your UI will perform noticeably more smoothly without resource-intensive animations occurring on your page. While this technique is undoubtedly destructive (it compromises your motion design intentions), an improvement in usability is always worth a reduction in elegance. After all, users visit your app to accomplish specific goals, not to admire how clever your UI work is. Never let animations get in the way of user intentions. If you’re still irked by the notion of stripping animations from your UI, keep in mind that users on weaker devices are accustomed to websites behaving slowly for them. So, if your site bucks the trend in a constructive way, they’ll be especially delighted by it and will be more likely to continue using it.

Find your performance threshold early on Continuing from the previous technique’s theme, it’s worth stressing that the advice in this chapter is especially relevant for mobile devices, many of which are slow relative to desktop computers. Unfortunately, we, as developers, often fail to consider this in our workflows: we routinely create websites within the pristine operating environments of our high-end desktops, which are likely running the latest-generation hardware and software available. This type of environment is divorced from the real-world environments of users, who are often not only using outdated hardware and software, but tend to have many apps and browser tabs running simultaneously. In other words, most of us work in development environments that are non-representationally high-performance! The side effect of this oversight is that your app may actually be noticeably laggy for a significant portion of your users. By the time you asking what frustrates them, they may have already lost interest in using it. The correct approach for a performance-minded developer is to determine the performance threshold early on in the development cycle. While developing your app, check its performance frequently on reference devices, which might include a lastgeneration mobile device plus a virtual machine running Internet Explorer 9. If you set a performance goal early on of being performant on your reference devices, then you can sleep soundly knowing that all newer devices will deliver even better performance for your users. Tip If you’re a Mac user, visit Microsoft’s Modern.ie website for information on how to run free virtual copies of old Internet Explorer versions. If you find that a reference device is too weak to power the motion design that you insist your app has, follow the advice from the previous technique: gracefully degrade animations on that reference device, and choose a faster device as your new (nondegraded) reference. For each testing device, remember to open several apps and tabs at once so you simulate users’ operating environments. Never test in a vacuum in which the only app running is your own. Keep in mind that remote browser testing (through services such as BrowserStack.com and SauceLabs.com) is not the same as live reference device testing. Remote testing services are appropriate for testing for bugs and UI responsiveness—not for animation performance. After all, the test devices running in the cloud aren’t using real hardware— they’re emulated versions of devices. Consequently, their performance is typically different than that of their real-world counterparts. Further, the lag time between what occurs on the virtual machine and what’s displayed on your browser window is too significant to get a meaningful gauge of UI animation performance. In short, you’ll need to go out and buy real devices for performance testing. Even if you’re a cash-strapped developer, don’t skimp on this. The few hundred dollars you spend

on test devices will be offset by the increased recurring revenue you’ll generate from happier users engaging more frequently with your buttery-smooth app. If you wind up with a handful of reference devices, also consider purchasing Device Lab, a versatile stand that props up all of your mobile devices on a single surface so you can easily eyeball the screens during testing. As a bonus, the device includes a nifty app that lets you control all the browsers across your devices at once so you don’t have to manually refresh each browser tab. Note Visit Vanamco.com to purchase and download Device Lab.

Visit Ebay to Buy Old Devices for Cheap Purchasing the most popular Android and iOS devices from each of these products’ major release cycles will give you a broad cross-section of the hardware and software environments that your users have. Here’s my recommended setup (as of early 2015): iPhone 4 or iPad 2 running iOS7 iPhone 5s (or newer) running the latest version of iOS Motorola Droid X running Android 2.3.x Samsung Galaxy SII running Android 4.1.x Samsung Galaxy S5 (or newer) running the latest version of Android You’re welcome to substitute any of the Android devices for devices of similar performance. What’s important here is that you’re using one device from each major Android release cycle (2.3.x, 4.1.x, and so on) so that you have a representative sample of the web browser performance from each one. Refer to http://developer.android.com/about/dashboards for a distribution of the most popular Android versions.

Wrapping up Performance affects everything. From how many devices can run your app, to the quality of the user experience, to the perception of your app’s technical competency, performance is a major tenet of professional web design. It’s not a “nice-to-have,” it’s a fundamental building block. Don’t relegate performance as a simple optimization to be made in hindsight.

Chapter 8. Animation Demo It’s time to get your hands dirty! This final chapter walks you through a full animation demo powered by Velocity. In going through the demo’s source, you’ll learn how Velocity’s core features complement one another to greatly improve UI animation workflow. This demo will also introduce you to advanced techniques for working with CSS’s transform properties, which are vital to web-based animation today. In short, you’re going to put together the skills you’ve accumulated throughout this book to make something really darn cool. Your goals in coding the demo are twofold: use terse and expressive animation code, and ensure maximum performance.

Behavior The demo consists of 250 circles floating in, out, and around the screen. Periodically, you’ll zoom in, then back out to the position where the virtual camera started. The first image presented momentarily shows a zoomed-in view. Note Before you continue reading, head on over to VelocityJS.org/demo.book.html to see a live preview of the demo. (You can right-click anywhere on the page then choose “View Source” to see the demo’s code.) The circle elements are simply normal divs with box-shadow and borderradius set in CSS. There’s no WebGL or Canvas animation going on here—just pure HTML element manipulation. (Given the volume of elements that are being animated at once, it’s quite impressive that this demo is capable of running so smoothly in the DOM!) Let’s break down the animation: It consists of div elements translating along the X, Y, and Z axes. The Z-axis dictates the depth of each element’s animation, whereas X and Y provide the general flowing, 2D movement seen across the screen. Concurrent to the elements’ individual movements is a larger perspective shift that occurs on the element containing all these divs. This perspective shift occurs every 3 seconds, and it creates a periodic zooming effect that makes the viewer feel as if he’s briefly traveling through the circles’ 3D space. The second graphic depicts the 3D scene in its zoomed-out view. Contrast this with the zoomed-in view shown in the first image.

How to Download the Code Sample The code behind this animation demo is available for download from peachpit.com. Here’s how to get it: 1. Go to www.peachpit.com/register and create or log in to your account. 2. Enter the book’s ISBN (978-0-13-409670-4) and click Submit. 3. Your “My Registered Products” page opens. Find the listing for this book, and click “Access Bonus Content.” 4. The page containing the download link opens—click to access the Animation Demo file entitled WebAnimationJS_DemoCodeSample.zip

Code structure Let’s take a look at the code that powers this demo. It is structured as follows: 5. Animation setup: The specification of parameters used for constraining animation movement. 6. Circle creation: The generation of the div elements to be animated. 7. Container animation: The code responsible for animating the circles’ parent element.

8. Circle animation: The code responsible for animating the circle elements themselves. Try to familiarize yourself with the broader strokes of the demo’s implementation so you can keep its full context in mind as you explore each individual code block in the upcoming sections: Click here to view code image /************************ Animation setup ************************/ /* Randomly generate an integer between two numbers. */ function r (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } /* Query the window’s dimensions. */ var screenWidth = window.screen.availWidth, screenHeight = window.screen.availHeight; /* Define the z-axis animation range. */ var translateZMin = -725, translateZMax = 600; /********************** Circle creation **********************/ var circleCount = 250, circlesHtml = ””, $circles = ””; for (var i = 0; i < circleCount; i++) { circlesHtml += “”; } $circle = $(circlesHtml); /****************************** Container animation ******************************/ $container .css(“perspective-origin”, screenWidth/2 + “px ” + screenHeight/2 + “px”) .velocity( { perspective: [ 215, 50 ], opacity: [ 0.90, 0.55 ] }, { duration: 800, loop: 1, delay: 3000 }); /*************************** Circle animation ***************************/ $circles .appendTo($container) .velocity({ opacity: [ function() { return Math.random() }, function() { return Math.random() + 0.1 } ],

translateX: [ function() { return “+=” + r(-screenWidth/2.5, screenWidth/2.5) }, function() { return r(0, screenWidth) } ], translateY: [ function() { return “+=” + r(-screenHeight/2.75, screenHeight/2.75) }, function() { return r(0, screenHeight) } ], translateZ: [ function() { return “+=” + r(translateZMin, translateZMax) }, function() { return r(translateZMin, translateZMax) } ] }, { duration: 6000 }) .velocity(“reverse”, { easing: “easeOutQuad” }) .velocity({ opacity: 0 }, 2000);

Code section: Animation setup This section’s code is copied below for easy reference: Click here to view code image /************************ Animation setup ************************/ /* Randomly generate an integer between two numbers. */ function r (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } /* Query the window’s dimensions. */ var screenWidth = window.screen.availWidth, screenHeight = window.screen.availHeight; /* Define the z-axis animation range. */ var translateZMin = -725, translateZMax = 600;

The first section, Animation setup, begins by defining a function r (abbreviated from "random") that lets you artificially constrain randomly generated integer values. This function takes min and max parameters, then outputs a random number between the min to max range (using some basic algebra). You’ll use this later when randomizing the animating elements’ CSS transform values within ranges that are predefined in the next two code blocks. The next section queries the window object to retrieve the monitor’s dimensions. By later referencing these values, you can ensure that the circles don’t animate too far offscreen (and consequently out of view). Animation setup concludes by defining the min and max values for the elements’ Zaxis movement. These values control how small (far away) or large (nearby) you want the circles to animate from their initial size. Specifically, it dictates that the circles can go as far as 725 pixels along the Z-axis away from the virtual camera (away from the screen), and as close as 600 pixels toward the camera. In this case, there’s no constraint of going off-screen, but the circle could become too distant to see or so close that it takes up the entire monitor. Basically, it’s a creative decision.

Code section: Circle creation Click here to view code image /********************** Circle creation **********************/ var circleCount = 250, circlesHtml = ””, $circles = ””; for (var i = 0; i < circleCount; i++) { circlesHtml += “”; } $circle = $(circlesHtml);

The demo’s second section, Circle creation, generates the primary div elements to be animated. Here, it first defines the desired number of circles as circleCount. Then, it defines a circlesHtml string to contain the circles’ collated HTML. Next, it iterates up to the circleCount number to generate the circles’ HTML. Notice that it uses the performance best practice of batching DOM additions, as detailed in Chapter 7, “Animation Performance.” It collates the markup for each div element onto a master circlesHtml string that’s later inserted into the DOM in a single action. (If you were to insert the div elements into the DOM one at a time, the negative performance impact would be significant: UI interaction in the browser would be frozen until the relatively slow element insertion process completed.) Finally, it wraps the circle elements in a jQuery element object so they can be easily manipulated as a group in the upcoming Circle animation section.

Code section: Container animation Click here to view code image /****************************** Container animation ******************************/ $container .css(“perspective-origin”, screenWidth/2 + “px ” + screenHeight/2 + “px”) .velocity( { perspective: [ 215, 50 ], opacity: [ 0.90, 0.55 ] }, { duration: 800, loop: 1, delay: 3000 });

3D CSS primer Let’s begin the first of the two animation sections of the codebase by focusing on the element that contains the circle elements. Before diving into the code, however, here’s a primer on how 3D animation works in the browser: In order for 3D transforms to work (for example, translateZ, rotateX, rotateY), the CSS specification requires that the perspective CSS property be set

on the element’s parent. In this case, that’s what the $container element is for. The greater the value that perspective is set to, the less distance Z-axis translations (via CSS’s translateZ) appear to move relative to their origin. In other words, if you want more exaggerated depth in your 3D animations, set the parent element’s perspective property to something low, such as 50px, which is in fact the value that the container element is set to in the demo’s CSS. In contrast, a higher perspective value, such as 250px, would result in less visible movement from the origin point for every pixel that the element’s translateZ property is incremented by. A separate and complementary CSS property is prospective-origin, which defines the angle at which the virtual camera is positioned. The virtual camera is the peephole through which the viewer sees 3D animation unfold in the browser. This section’s code block uses jQuery’s $.css() function to set a perspective-origin value on the container element that results in the camera being positioned at the center of the page, creating a perpendicular view of the 3D animation. This perpendicular view results in the appearance of circles flying directly toward and away from the viewer. Specifically, this code section sets perspective-origin to the point on the page that’s at half the browser’s height and half its width—the center point of the page. This leverages the window dimensions queried in the Animation setup section. With that context out of the way, let’s explore this section’s code.

Properties This section’s code, reproduced below for easy reference, creates the demo’s zooming in and out effect: Click here to view code image $container .css(“perspective-origin”, screenWidth/2 + “px ” + screenHeight/2 + “px”) .velocity( { perspective: [ 215, 50 ], opacity: [ 0.90, 0.55 ] }, { duration: 800, loop: 1, delay: 3250 });

While the prospective-origin property is set once on the container element and thereafter left alone, the prospective property is being animated by Velocity. This is necessary because the intended effect of the demo is to keep the vantage point into the scene stationary (perpendicular), but to exaggerate then de-exaggerate the distance of the elements from the virtual camera, which is where the perspective property’s animation comes in. Specifically, this section uses Velocity to animate the perspective CSS property to a final value of 215px from a starting value of 50px. By passing in an array as an animation property’s value, you’re forcefully specifying

the final value to animate the property toward (215px, in the case above) as well as the initial value to animate from (50px, in the case above). While you certainly could have passed the property a single integer value as is typically expected by Velocity, the forcefeeding syntax provides increased control over the property’s complete animation path. You might be wondering, isn’t force-feeding unnecessary since Velocity knows how to retrieve a CSS property’s starting value on its own? While that is Velocity’s standard behavior when an integer is passed in as a value instead of an array, this isn’t always a desirable behavior due to the performance drawbacks inherent to querying the DOM for a property’s starting value. What the force-feeding syntax allows you to do is explicitly pass in a starting value so that Velocity can avoid querying the DOM for a property whose starting value you already know. In other words, the 50px starting value used in the perspective code above is the same value you initially set the container element’s perspective property to in the CSS stylesheet. You’re simply repeating the value here. Notice that this same force-feeding technique is used on the element’s opacity property as well: it’s animated to a final value of 0.90 from a starting value of 0.55 since that’s what the property was set to in the CSS. As discussed thoroughly in Chapter 7, “Animation Performance,” DOM queries are indeed the Achilles’ heel of performant animation: the browser performs resourceintensive calculations to determine the visual state of an element. While it’s not important to the demo’s performance that you include this performance optimization, since the associated Velocity animation isn’t being triggered repeatedly inside a loop, it’s included nonetheless to contrast force-feeding’s secondary use, which you’ll learn about later in this chapter. The net effect of animating the perspective and opacity is that all of the container’s circle elements appear to zoom in closer to the virtual camera while animating to an increased brightness (opacity goes from 0.55 to 0.90). The opacity boost mimics the way that light behaves in the real world: the closer the viewer is to the objects, the brighter they appear!

Options The final section of Container animation code includes the options being passed into Velocity: duration, which is self explanatory; delay, which inserts a time-out at the start of the animation, and loop, which loops an animation back and forth between the values defined in the properties map and the element’s values prior to the animation occurring. Specifically, by setting loop to 2, you’re telling Velocity to animate to the values in properties map, back to where they were before, then to repeat this full loop iteration once more after a 3000ms delay. Note When delay is set alongside loop, the delay occurs between each of the loop’s alternations. Using delay creates a pleasant pause so that the zoom-in and zoom-out effect doesn’t zigzag back and forth abruptly.

Code section: Circle animation This is where things start getting interesting. Let’s take a look the circle animation, in which you’re simultaneously animating their X-, Y-, Z-axis translations individually. You’re also animating their opacity. Click here to view code image /*************************** Circle animation ***************************/ $circles .appendTo($container) .velocity({ opacity: [ function() { return Math.random() }, function() { return Math.random() + 0.1 } ], translateX: [ function() { return “+=” + r(-screenWidth/2.5, screenWidth/2.5) }, function() { return r(0, screenWidth) } ], translateY: [ function() { return “+=” + r(-screenHeight/2.75, screenHeight/2.75) }, function() { return r(0, screenHeight) } ], translateZ: [ function() { return “+=” + r(translateZMin, translateZMax) }, function() { return r(translateZMin, translateZMax) } ] }, { duration: 6000 }) .velocity(“reverse”, { easing: “easeOutQuad” }) .velocity({ opacity: 0 }, 2000);

Value functions Unlike the static animation property values used in the previous section (for example, [ 215, 50 ]), this section uses functions for property values: each property is force-fed an array of start and end values that are dynamically produced by functions. Let’s briefly explore these value functions, which are a unique feature of Velocity. Note Read more about value functions at VelocityJS.org/#valueFunctions. Value functions let you pass in functions as animation property values. These functions trigger at run-time, and are called individually for each element animated in a set. In the demo, the set in question is the circle divs contained within the $circles jQuery element object. Consequently, each circle element property will be assigned its own randomized value once the animation begins. The only other way to achieve differentiation between animation properties in a set of elements is to animate the elements separately by looping through them, which gets messy and performs badly. This is the benefit of value functions—you keep dynamic animation code terse and

maintainable. Notice that, to produce the randomized values, this section of code leverages our r helper function that was defined in Animation setup. (As a reminder, the r function returns a randomized integer value constrained by its min and max arguments.) You’ll learn more about this function momentarily.

Opacity animation The opacity property animates from and toward randomized values. In the case of the starting value, you’re giving the randomized value a slight boost to ensure that the elements are never too close to being invisible—after all, you want the viewer to see what you’re animating! The animation of opacity results in a smattering of circles all over the page that have varying opacities from the very first frame. Differentiated opacities create a nice gradient effect that adds visual richness to the demo. This code takes advantage of force-feeding for a purpose other than performance optimization: value functions are being force-fed to dynamically generate start values for the elements that have yet to be inserted into the DOM, which means that you’re successfully avoiding writing an entirely new code block just to set the initial CSS states of the circle elements. You’re dynamically providing unique starting positions in the same line of code responsible for animating those positions. As discussed thoroughly in Chapter 4, “Animation Workflow,” you should strive for this level of expressiveness in all of your animation code.

Translation animation For easy reference, here’s this section’s code once again: Click here to view code image /*************************** Circle animation ***************************/ $circles .appendTo($container) .velocity({ opacity: [ function() { return Math.random() }, function() { return Math.random() + 0.1 } ], translateX: [ function() { return “+=” + r(-screenWidth/2.5, screenWidth/2.5) }, function() { return r(0, screenWidth) } ], translateY: [ function() { return “+=” + r(-screenHeight/2.75, screenHeight/2.75) }, function() { return r(0, screenHeight) } ], translateZ: [ function() { return “+=” + r(translateZMin, translateZMax) }, function() { return r(translateZMin, translateZMax) } ] }, { duration: 6000 })

.velocity(“reverse”, { easing: “easeOutQuad” }) .velocity({ opacity: 0 }, 2000);

It’s time to examine the translate animations, which individually translate the circle elements’ positions within the demo’s 3D space. All three axes are animating from a randomized start value toward a randomized end value. The value operator, which consists of the plus sign followed by the equals sign (+=), tells the animation engine to animate properties incrementally from their starting values. In other words, the += value operator instructs the animation engine to treat the ending value as a relative value. In contrast, the default behavior of an animation engine is to interpret an end value in absolute terms. As with opacity, this code section leverages force-feeding and value functions for their expressivity and performance benefits. In particular, the circles’ movement is constrained within ranges relative to the screen dimensions for the X and Y axes, and relative to the predefined min and max depth values for the Z-axis. (As a reminder, these values were set in the Animation setup section.) In the case of the X and Y axes, there’s an arbitrary fudge factor (notice the division by 2.75) to reduce how spread out the elements animate. This value is simply a creative decision; tweak it to suit your aesthetic preference. Finally, the options object specifies that this entire animation should occur over a duration of 6000ms.

Reverse command After the primary Velocity animation call, the chain continues with a call to Velocity’s reverse command. Reverse does exactly what it sounds like it: it animates the target elements back to their initial values prior to the previous Velocity call taking place. In this unique case, since start values have been force-fed into the previous Velocity call, those are the start values that reverse will animate back toward. One of my reasons for including the reverse command in this demo is to extend the demo’s overall animation duration with a single line of maintainable and expressive code. (While you could double the duration of the animation from 6000ms to 12000ms, this would result in slowing down the movement of the circles.) The convenience of the reverse command is avoiding having to respecify—by hand—all of the animation start values. It would have been a huge mess to accomplish this manually since you would have had to first store all of the randomly generated start values into memory so you could animate back to them. Hence, reverse is yet another great Velocity feature that allows the demo to accomplish a lot with just a few lines of code. Velocity’s reverse command defaults to the options object used in the previous Velocity call—including its duration, easing, and so on. In this case, since the previous call used a duration of 6000ms, so will the reverse call. The reverse command also lets you specify a new options object to extend onto the previous one. This demo uses a new easing type of easeOutQuad for added motion design flair in the animation’s reverse direction.

Tip To preview the behavior of the popular easing types, visit http://easings.net. When the reverse animation completes, a final Velocity call fades the elements out of view by transitioning their opacity values to 0 over a duration of 2000ms. This completes the demo by leaving the browser’s canvas in the same visual state it began in: clean and empty! Your work here is done.

Wrapping up From force-feeding, to value functions, to reverse, this walkthrough has illustrated the power of the Velocity animation engine. Hopefully, this chapter has convinced you that this book’s focus on Velocity was worthwhile. In fewer than 75 lines of terse, legible, and performant code, you’ve created a rich 3D scene unlike anything you’ve seen before in pure HTML. Let this demo serve as a concrete example of just how simple intricate-looking animations can actually be—especially when you use the right tools and employ best practices. My hope is that this book has distilled the beautiful animation work you’ve seen across the web into a set of tenets that are easy to grasp and follow in pursuit of your own motion design. Now, go and design some beautiful websites and apps! Once you’ve put together something cool, show me on Twitter: twitter.com/shapiro.

Index Symbols and Numbers $.animate() 13 3D CSS primer on 156 transforms 96

A Adobe After Effect, animating text and 80 Adobe Photoshop, SVG and 104 Alerts, leveraging user response 42–43 Android purchasing older devices from eBay 144 realities of web performance 118 Animation demo behaviors 148–149 code section for animation setup 153–154 code section for circle animation 160–164 code section for circle creation 154–155 code section for container animation 156–159 code structure 150–152 overview of 147 review 165 Animation libraries bypassing jQuery 6 page scrolling functions 7 SVG support 108 types of 14 Animation reversal, performance features of JavaScript 7–8 Animations. See also Motion design breaking into steps 48–49 effects on neighboring elements 130

limiting in motion design 45 mirroring 44 older browsers problem 139 older browsers solutions 139–140 optimized coding approach to organizing sequenced animations 66–68 performance. See Performance reducing concurrency 43 reducing variety 44 staggering 49 standard coding approach to organizing sequenced animations 65–66 of text. See Text animation workflows. See Workflows Animations, with SVG animated logo example 112–113 overview of 109 passing properties 109 positional attributes vs. transforms 110–111 presentational attributes 110 Arguments, Velocity 16–18 Attributes, SVG markup 105–106

B backgroundColor property, Velocity support for CSS color properties 31–32 backwards option, benefits in text animation 92–93 Baselines, load testing and 120 Batching DOM additions code section for circle creation 155 problem 126–127 solutions 127–128 begin option, Velocity 24 Bézier curves, easing values in Velocity 22 Blast.js customClass option 85–86

delimiter option 85 generateValueClass option 86–87 how it works 83–84 installing on pages 84–85 preparing text elements using 82–83 reverse option 88–89 tag option 87–88 Blue, Velocity support for CSS color properties 31–32 body tag, installing Blast and 84 Bold text, tag option in Blast and 88 Boolean values, generateValueClass option in Blast 86–87 borderColor property, Velocity support for CSS color properties 31–32 border-radius set property, in behavior of animation demo 148 Bottlenecks problem 133 solutions 133–134 Bottom line, performance affecting 117 box-shadow property, CSS in behavior of animation demo 148 overview of 138 Browsers animations on older browsers problem 139 animations on older browsers solution 139–140 bottlenecks and 133 finding performance threshold early on 141–143 positional attributes vs. transforms and 110 realities of web performance 118 support for older versions 4 BrowserStack.com, testing browsers on 142 Buttons, uses of SVG 109

C Callback functions, begin and complete options in Velocity 24

Chaining effects and 69 using Velocity with jQuery and 16 in Velocity 20 character delimiter, Blast.js 82, 85 Chrome, realities of web performance 118 circle element in behavior of animation demo 148 code section for circle animation 160–164 code section for circle creation 154–155 code structure for animation demo 153–154 SVG presentational attributes 106 SVG styling 106 Classes customClass option in Blast 85–86 generateValueClass option in Blast 86–87 Code/coding techniques code section for animation setup 153–154 code section for circle animation 160–164 code section for circle creation 154–155 code section for container animation 156–159 code structure for animation demo 150–152 creating images through code in SVG 104 optimized approach to organizing sequenced animations 66–68 optimized approach to packaging effects 70–72 optimized approach to separating styling from logic 60–65 standard approach to organizing sequenced animations 65–66 standard approach to packaging effects 69 standard approach to separating styling from logic 59–60 what good code looks like 57 color property, Velocity support for CSS color properties 31–32 Colors

performance benefits of using opacity instead of 132 Velocity options 31–32 complete option, Velocity 24 Compression, SVG and 104 Concurrency problem 133 reducing in motion design 43 solutions 133–134 Consistency, pattern recognition and understanding and 44 Containers code section for container animation 156–159 code structure for animation demo 153–154 SVG () 105 text elements 80 Conventions, in making design choices 41 CSS 3D primer 156 animation effects on neighboring elements 130–131 appropriate uses of CSS workflow 57–58 benefit of switching to JavaScript for segregation of logic 62 comparing SVG positional attributes with CSS transforms 110 comparing Velocity display and visibility options with 27–29 comparing Velocity properties with CSS properties 18–19 comparing Velocity values with CSS values 20 easing values in Velocity 22 fine-grained control of Blast elements 94 issues with CSS workflow 56–57 JavaScript compared with 4–9 perspective properties 156–157 separating styling from logic 59–60 sneaky images and 138 SVG styling compared with 107

Velocity arguments corresponding to 16 Velocity support for CSS transform property 32 customClass option, Blast.js 85–86

D Data transfer indicators, preview options in motion design 41 Debouncing, event handlers 135–136 delay option, Velocity 26 Delay values staggering durations and 91 timing multipliers and 73 Delimiters, Blast.js 82, 85 Design techniques. See also Motion design page scrolling in Web design 7 timing multipliers 73–74 VMD (Velocity Motion Designer) 74–76 Device Lab 142 display option, Velocity 27–28 div in behavior of animation demo 148 Blast.js 82 HTML elements 83 tag option in Blast 88 DOM (Document Object Model) batching DOM additions for improved performance 126–128, 155 layout thrashing problem 121–122 layout thrashing solution 122–123 retrieving raw DOM elements 33–34 SVG elements as DOM elements 104 duration option, Velocity 21 Durations limiting in motion design 45 staggering 91

timing multipliers and 73

E Easing options, Velocity 21–23 eBay, purchasing older devices from 144 Effects fade effect in UI pack 91 fanciful effects in text 96 flourishes in text 97–98 optimized coding approach to packaging 70–72 standard coding approach to packaging 69 transition.fadeOut effect in UI pack 92 Elegance aspects, of motion design breaking animation into steps 48–49 flowing from triggering elements 49 graphics use 50 not being frivolous 47 opacity use 48 overview of 39–40 staggering animations 49 using appropriate personality features 47–48 Element nodes, HTML 83 Elements animation effects on neighboring elements 130–132 circle element. See circle element fine-grained control of Blast elements 94 flowing from triggering elements 49 HTML element manipulation 148 image rendering problems 137 image rendering solutions 137–138 JEOs (jQuery element objects) 123–124, 126–128 preparing text elements for animation using Blast.js 82–83 retrieving raw DOM elements 33–34

span elements 87–88 SVG elements compared with HTML elements 104 text elements 80 eq() function, jQuery 94 Event handlers, debouncing 135–136 Experimentation, benefits of repeatedly experimenting 51–52

F Fade effect, in UI pack 91 Familiarity, use of conventions in making design choices 41 fill, SVG presentational attributes 105 styling 107 Flags, leveraging user response 42–43 Flourishes, in text 97–98 Flow, creating from triggering elements 49 Force-feeding feature (Velocity), for avoiding layout thrashing problem 124–125 Frivolous design, uses and abuses of 47

G generateValueClass option, Blast.js 86–87 gets JEOs as culprit in layout thrashing 123–124 layout thrashing and 121–122 Global timing multipliers 73–74 Gradients, CSS 138 Graphics in elegant motion design 50 SVG and 104, 109 Green, Velocity support for CSS color properties 31–32 GSAP animation library 14

H Height, SVG presentational attributes 105

Hidden setting, display and visibility options 28 Hover state animations, uses of CSS 6, 57–58 HTML coding web pages 80 element manipulation 148 element nodes 83 SVG elements compared with HTML elements 104

I Images creating through code in SVG 104 rendering problems 137 rendering solutions 137–138 sneaky image problems 139 sneaky image solutions 139–140 img element 138 Incentives, visceral nature of interactions and 43 Infinite looping, in Velocity 25–26 See also Loops Inkscape 104 Inline status indication, engaging users in tasks 42 In-progress indicators, preview options in motion design 41–42 Internet Explorer animations on older browsers problem 139 finding performance threshold early on 141–143 positional attributes vs. transforms and 110 realities of web performance 118 iOS, purchasing older devices from eBay 144 Irreversible actions, indicators for 43

J Janks (stutters), layout thrashing and 121 JavaScript vs. CSS

animation reversal feature in JavaScript 7–8 overview of 4 page scrolling feature in JavaScript 7 performance benefits 6 physics-based motion in JavaScript 8 review 10 workflow maintenance 9 JEOs (jQuery element objects) batching DOM additions for improved performance 126–128 as culprit in layout thrashing 123–124 jQuery easing options 22–23 fine-grained control of Blast elements 94 installing 15 JavaScript animation libraries that bypass 6 required by Blast 84–85 slowness of animation features in 4 standard coding approach to separating styling from logic 59 using Velocity with 16 using Velocity without 33–34 Velocity compared with 13 jQuery element objects. See JEOs (jQuery element objects)

L Latency, search engine performance and 117 Layout thrashing force-feeding feature in Velocity for avoiding 124–125 JEOs (jQuery element objects) as culprit in 123–124 problem 121–122 solutions 122–123 Load testing, realities of web performance and 120 Logic optimized coding approach to separating from styling 59–60

standard coding approach to separating from styling 59 Logos animated logo example in SVG 112–113 uses of SVG 109 loop option, Velocity 25–26 Loops code section for container animation 159 layout thrashing and 121–122

M Maintenance, of workflows 9 Markup, SVG 105–106 Max values, code section for animation setup 154 Min values, code section for animation setup 154 Mock feature, Velocity 74 Motion design alerts and flags for leveraging user response 42–43 appropriate personality features 47–48 breaking animation into steps 48–49 conventions in making design choices 41 engaging users in tasks 42 experimenting repeatedly 51–52 flowing from triggering elements 49 graphics use 50 indicators of severity of irreversible actions 43 limiting animations 45 limiting durations 45 mirroring animations 44 not being frivolous 47 opacity use 48 overview of 37 previewing outcomes 41 reducing concurrency 43

reducing variety 44 review 53 staggering animations 49 utility and elegance of 39–40 UX (user experience) improved by 38 visceral nature of interactions 43 Mozilla Developer Network, directory of SVG elements 114 Multi-animation sequences, solutions to concurrency issues 134 Multipliers, timing multipliers as design technique 73–74

O Opacity animation of 161 flourishes in text 97–98 going beyond overuse of 48 performance benefits of using instead of color 132 opacity property 161 outlineColor property, Velocity support for CSS color properties 31–32

P Page scrolling, performance features of JavaScript 7 See also scroll command Performance animation effects on neighboring elements problem 130 animation effects on neighboring elements solution 131–132 animations on older browsers problem 139 animations on older browsers solution 139–140 batch DOM additions problem 126–127 batch DOM additions solutions 127–128 bottleneck concurrency problems 133 bottleneck concurrency solutions 133–134 features of JavaScript 6 finding performance threshold early on 141–143

force-feeding feature in Velocity for avoiding layout thrashing 124–125 image rendering problems 137 image rendering solutions 137–138 JEOs (jQuery element objects) and 123–124 layout thrashing problem 121–122 layout thrashing solution 122–123 overview of 117 realities of web performance 118–120 review 145 scroll and resize event problems 135 scroll and resize event solutions 135–136 sneaky image problems 139 sneaky image solutions 139–140 Personality, using appropriate personality features in motion design 47–48 Perspective properties, CSS 156–157 Physics-based motion, performance features of JavaScript 8 Pixels, image rendering problems 137 Positional attributes, SVG 110–111 Presentational attributes, SVG 105, 110 Previews, previewing outcomes in motion design 41 Properties in behavior of animation demo 148 CSS perspective properties 156–157 CSS shadow properties 138 passing properties in SVG animations 109 Velocity 18–19 Velocity support for CSS color properties 31–32 px, as default unit in Velocity 19–20

R Random numbers, code section for animation setup 153 Red, Velocity support for CSS color properties 31–32 resize events

performance problems 135 performance solutions 135–136 reverse command animation reversal feature in JavaScript 7–8 code section for circle animation 163–164 in Velocity 30 reverse option, Blast.js 88–89 RGB (red, green, blue), Velocity support for CSS color properties 31–32 Rotation, CSS transform property 32

S Safari, realities of web performance 118 Scalable vector graphics. See SVG (scalable vector graphics) Scale, CSS transform property 32 scroll command overview of 30–31 Velocity page scrolling 7 scroll events performance problems 135 performance solutions 135–136 Scrolling, page animation and 137 Search engines, latency and 117 sentence delimiter, Blast options 84–85 Sequence running, in UI pack 65 Sequenced animations optimized coding approach to organizing 66–68 standard coding approach to organizing 65–66 sets, layout thrashing and 121–122 setup code section for animation setup 153–154 code structure for animation demo 150 Shadow properties, CSS 138 Shorthand features, in Velocity 20

Sketch program 104 Smartphones animations on older browsers and 139 purchasing from eBay 144 realities of web performance 118 Sneaky images, performance issues 139–140 Span elements animating text and 80 tag option in Blast 87–88 Spring physics, easing values in Velocity 23 stagger feature, in UI pack 133–134 Staggering animations 49 solutions to concurrency issues 133–134 solutions to image rendering issues 138 text animation and 91 Status indicators data transfer indicators 41 loading text and 97 uses of SVG 109 Stutters (janks), layout thrashing and 121 Style sheets, JavaScript vs. CSS 4 See also CSS Styling optimized coding approach to separating from logic 60–65 standard coding approach to separating from logic 59–60 SVG 107 SVG (scalable vector graphics) animated logo example 112–113 animating graphic components 50 animations 109 creating images through code 104

going beyond rectangles 111 markup 105–106 overview of 103 passing properties 109 positional attributes vs. transforms 110–111 presentational attributes 110 review 112–113 styling 107 support for 108 SVG Pocket Guide (Trythall) 114 Syntax arguments in Velocity 17–18 SVG markup 105–106

T Tables, HTML elements 83 tag option, Blast.js 87–88 Text animation customClass option in Blast 85–86 delimiter option in Blast 85 flourishes in text 97–98 generateValueClass option in Blast 86–87 how Blast.js works 83–84 installing Blast on page 84–85 overview of 79 preparing text elements using Blast.js 82–83 replacing existing text 90 reverse option in Blast 88–89 review 100 staggering option 91 standard approach to 80 tag option in Blast 87–88 transitioning individual text parts 94–95

transitioning text out of view 91–93 transitioning text using fanciful effects 96 Text nodes 80 text-shadow property, CSS 138 Thresholds, finding performance threshold early 141–143 Timing control delay option 26 JavaScript vs. CSS 4 Timing multipliers, as design technique 73–74 transform property, Velocity 31–32 Transforms 3D CSS primer 156 3D transforms 96 animation effects on neighboring elements and 131 comparing SVG positional attributes with CSS transforms 110–111 transition.fadeOut effect, in UI pack 92 transition.perspectiveDown effect, in UI pack 96 Transitions individual text parts 94–95 limiting durations 45 replacing existing text 90 staggering durations 91 text out of view 91–93 text using fanciful effects 96 text visibility 80 Translations 3D CSS primer 156 animation effects on neighboring elements and 131 animation of 162–163 code section for circle animation 160 CSS transform property 32 mirroring and 44

Triggers, flowing from triggering elements 49 Trigonometric easings, easing values in Velocity 22

U UI (user interface) conventions in making design choices 41 motion design improving user experience 38 UI animation libraries 14 UI animation workflow 65 UI pack fade effect in 91 getting and installing 65 optimized coding approach to packaging effects 70–72 stagger feature in 133–134 transition.fadeOut effect 92 transitioning text fancifully 96 Unit types, values in Velocity 19–20 User experience. See UX (user experience) User interface. See UI (user interface) Utility aspects, of motion design alerts and flags for leveraging user response 42–43 conventions in making design choices 41 engaging users in tasks 42 indicators of severity of irreversible actions 43 limiting animations 45 limiting durations 45 mirroring animations 44 overview of 39–40 previewing outcomes 41 reducing concurrency 43 reducing variety 44 visceral nature of interactions 43 Utility function, Velocity 66

UX (user experience) motion design improving 38 performance affecting 117 physics-based motion in JavaScript enhancing 8

V Values code section for animation setup 154 value functions 161 Velocity 19–20 Variety, reducing in motion design 44 Velocity animation demo. See Animation demo arguments 16–18 begin and complete options 24 chaining 20 color options 31–32 compared with jQuery 13 containing animation logic within 29 delay option 26 display and visibility options 27–28 downloading and installing 15 duration option 21 easing options 21–23 force-feeding feature for avoiding layout thrashing 124–125 loop option 25–26 mock feature 74 optimized coding approach to organizing sequenced animations 66–68 page scrolling functions 7 passing properties in SVG animations 109 physics-based motion 8 properties 18–19 resource for SVG attributes and styling properties 114

reverse command 30 review 33–34 scroll command 30–31 transform property 31–32 types of animation libraries 14 UI pack 65 using with jQuery 16 using without jQuery 33–34 values 19–20 Velocity Motion Designer (VMD) 74–76 Video. See also Images image rendering problems 137 image rendering solutions 137–138 Visibility replacing existing text 90 transitioning text out of view 91–93 transitioning text visibility 80 visibility option, Velocity 27–28 Visual processing, leveraging primal instincts in motion design 42–43 VMD (Velocity Motion Designer) 74–76

W Web design, use of page scrolling in 7 Web performance, realities of 118–120 Width, SVG presentational attributes 105 word delimiter, Blast options 85 Workflows CSS appropriate uses 57–58 CSS issues 56–57 maintainability of 9 optimized coding approach to organizing sequenced animations 66–68 optimized coding approach to packaging effects 70–72 optimized coding approach to separating styling from logic 60–65

overview of 55 review 77 standard coding approach to organizing sequenced animations 65–66 standard coding approach to packaging effects 69 standard coding approach to separating styling from logic 59–60 timing multipliers as design technique 73–74 VMD (Velocity Motion Designer) 74–76

X x value, SVG presentational attributes 105

Y y value, SVG presentational attributes 105

Code Snippets