Easing

Easing tweaks the behavior of interpolators by controlling the time (t) argument. We use this to make our animations feel more natural, to add some bounce elasticity, and so on. Mostly, we use easing to avoid the artificial feel of linear animation.

Let's make a quick comparison of the easing functions provided by D3 and see what they do.

We will start putting everything in separate files because it helps us manage our code when we start extending our charts. First, create lib/chapter5/index.js and add the following:

import easingChart from './easingChart'; 
easingChart(true);

Next, create a new file, lib/chapter5/easingChart.js, and add a new function enclosure:

import * as d3 from 'd3'; 
import chartFactory from '../common';
function easingChart(enabled) {
if (!enabled) return;
const chart = chartFactory();
}
export default easingChart;

Next, we need an array of easing functions and a scale for placing them along the vertical axis. Put this after const chart:

const easings = ['easeLinear', 'easePolyIn(4)', 'easeQuadIn', 'easeCubicIn', 'easeSinIn', 'easeExpIn', 'easeCircleIn', 'easeElasticIn(10, -5)', 'easeBackIn(0.5)', 'easeBounceIn', 'easeCubicIn', 'easeCubicOut', 'easeCubicInOut'];
const y = d3.scaleBand()
.domain(easings)
.range([50, 500]);
const svg = chart.container;

You'll note that easePolyIn, easeElasticIn, and easeBackIn take arguments; since these are just strings, we'll have to manually change them into real arguments later. The easePolyIn easing function is a polynomial, so easePolyIn(2) is equal to easeQuadIn and poly(3) is equal to easeCubicIn. Alternatively, for those of us who stopped paying attention to math toward the end of our secondary school, the higher the poly argument value, the deeper the curve; for instance, poly(4) (equivalent to quart) has a fair bit of delay at the beginning, the end, or both, depending on where you set the easing (see following code snippet). The higher the number, the more dramatic the delay. Have a play with it, do what feels right.

The easeElasticIn easing function simulates an elastic and the two arguments control tension. I suggest playing with the values to get the effect you want. The back easing function is supposed to simulate backing into a parking space. The argument controls how much overshoot there will be.

The easings at the end include an -out modifier as well as an -in modifier. These mean the following:

  • -In: Normal behavior
  • -Out: Reverses the easing direction
  • -InOut: Copies and mirrors the easing function from [0, 0.5] and [0.5, 1]
  • -outIn: Copies and mirrors the easing function from [1, 0.5] and [0.5, 0]

You can add these to any easing function, so play around. Now we will render a bunch of circles animated using each easing:

  easings.forEach((easing) => { 
const transition = svg.append('circle')
.attr('cx', 130)
.attr('cy', y(easing))
.attr('r', (y.bandwidth() / 2) - 5)
.transition()
.delay(400)
.duration(1500)
.attr('cx', 400);
});

We loop over the list with an iterator that creates a new circle and uses the y() scale for vertical placement and y.bandwidth() for circle size. This way, we can add or remove examples easily. Transitions will start with a delay of just under half a second to give us a chance to see what's going on. A duration of 1,500 milliseconds and a final position of 400 should give enough time and space to see the easing.

We define the easing at the end of this function, before the }); bit:

    if (easing.indexOf('(') > -1) { 
const args = easing.match(/[0-9]+/g);
const funcName = easing.match(/^[a-z]+/i).shift();
const type = d3[funcName];
transition.ease(type, args[0], args[1]);
} else {
const type = d3[easing];
transition.ease(type);
}

This code checks for parentheses in the ease string, parses out the easing function and its arguments, and feeds them to transition.ease(). Without parentheses, ease is just the easing type.

Note that in D3 v4, we use the symbols attached to the D3 object, for instance, d3.easeCubicIn. Previously, you'd supply a string to transition.ease(), such as 'cubicIn'.

Let's add some text so that we can tell the examples apart:

    svg.append('text') 
.text(easing)
.attr('x', 10)
.attr('y', y(easing) + 5);

Ensure that the server's running ($ npm start if not) and visit http://127.0.0.1:8080.

In order to prevent having to repeat the preceding four lines over and over, I'll take it on faith that you know how to import and instantiate the modules we're creating at this point, in addition to knowing how to load the development server. I'll, thus, leave out that part from here on.

The visualization is a cacophony of dots:

The preceding figure doesn't quite showcase the animation, so you should really try this one in the browser. Alternatively, you can take a look at the easing curves at http://easings.net/.

Easings are a nice finishing touch to put on most animations. Most things in the real world don't have constant acceleration; a good rule of thumb is to match whichever element you're animating with an easing appropriate for its size in relation to the page. In other words, small elements should generally move faster than large elements and have tighter -in and -out easings. The most important thing is to think about how stuff should logically move instead of just slapping a 1-second linear fade-in on everything.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset