Car Rig

Learn how to create a simple but effective car rig

12-00

1. Setup

this simple car rig will automate the rotation of the wheels and the orientation of the car along the motion path. You can use your own car model imported from Photoshop or Illustrator, or create it directly in AE with shape layers. Make sure that each wheels are on a separate layer, and that anchor point is centered.

The simplest hierarchy would be 3 layers:

  • Car body
  • Front wheel
  • Rear wheel

Start by creating the road to be used as a motion path; again, the easiest way would be to create it directly in after effects using shape layers, but you can also import an external file. Doing so will require an extra step, you need to create a mask to outline the curves of the road.

12-01

2. Drive!

  • Create a new Null Object(“Drive”)
  • Copy the position property of the front wheel to the Null Object(“Drive”)
  • Use the pick whip to link all the car layers to the Null Object(“Drive”)
  • Copy the road path from your shape layer or the mask outline to the position property of the Null Object(“Drive”). Make sure you copy the Path and not the object/mask to the position property.

Because the motion path moves the object along its anchor point, we need to offset the Y position of half the diameter of the wheel.

  • Add an expression to the Null Object(“Drive”)

If you used a Shape layer, it is easy, you need to get the diameter from the ellipse shape property:

var d = thisComp.layer(“wheel_F”).content(“Ellipse 1”).content(“Ellipse Path 1”).size[0];

If you imported the layer and don’t know the exact diameter, the easiest will be to create an Effect > Expression Controls > Slider Control, and adjust manually.

var d = effect(“Slider Control”)(“Slider”);

End the expression code with:

[value[0],value[1]-d/2]

We only want to affect the Y position (second value in the array) by half of the diameter (-d/2)

3. Orientation

If you toggle on Transform > Auto-orient > Along the path, you can see that the result are more than unexpected. It orients the front wheel, without taking into consideration the rest of the car.

We will solve this problem with an expression on the Null Object(“Drive”) comparing values over time.

  • Remove Auto-Orient if you toggled it on
  • Add an Effect > Expression Controls > Slider Control to Null Object(“Drive”) and rename it to offset.
  • Add an expression to Null Object(“Drive”).rotation; first store the new controller value and convert decimals to Frames for more flexibility*:
var offset = framesToTime(effect(“offset (in frames)”)(“Slider”));

*time is evaluated in seconds in expressions, not in frames

  • Create 2 variables to store the positions at current time and past time
var from = transform.position;
var to = transform.position.valueAtTime(time-offset);
  • The last part of the expression evaluates the distance between the 2 wheels; if you don’t understand it, please review the previous topic Line Connectors
radiansToDegrees( Math.atan2( from[1]-to[1], from[0]-to[0] ) )
  • Adjust manually the slider(“offset”) so that the rear wheel touches the ground (in positive values)*

*This value depends on the speed (time between the start/end keyframes of the position animation) and the distance travelled in pixels. It should be possible to accumulate values over time to evaluate it, but honestly, it is easier and faster this way.

This setup is not perfect, you will notice sometimes the rear wheel does not stick exactly to the road when the road distortion is heavier. It has to do with the distance between the 2 wheels being forced to always stay the same, despite the distance travelled. But the viewer should not even notice it so why bother? You can still adjust manually if it is really noticeable.

12-02

4. Wheels rotation

  • Use the pick whip to link the rotation of the rear wheel with the front wheel

Geometry: circumference ?

12-03

  • Add an expression to the rotation to store the variables
var d = content(“Ellipse 1”).content(“Ellipse Path 1”).size[0];
var p = thisComp.layer(“Drive”).transform.position;
  • Write the expression result : 360º / Circumference * Position

360 / (Math.PI*d) * p[0]

This expression evaluates the rotation speed (360/C) and uses X Position to know how many pixels the car travelled. You can check out CreativeCow Vehicle rig for a more in depth explanation.

12-04

DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download the AE project (rename .key to .zip after download)

download

Line Connectors

Learn how to create a line between 2 layers

REMINDER
If you are an absolute beginner, please start your learning by checking the essential resources below:
http://www.jjgifford.com/expressions/basics/index.html
https://helpx.adobe.com/after-effects/using/expression-basics.html
http://www.motionscript.com

1. Setup

  • show the grid and the rulers, and activate snapping (from the “view” menu in the menu bar).
  • draw a line shape from the center of the composition to +100px to the right; for example, if you work in 1920×1080, draw a line from [960,540] to [1060,540]
  • rename shape layer to “line”
  • Create 2 shape layers, conveniently renamed “from” and “to”, or import the assets that you want to link with a line, and make sure both layers anchor points are centered.
  • Reposition one layer to the right, and the other to the left side of the composition.

2. Expressions

  • Add an expression to shape layer(“line”)> shape 1> Position, to link the line start point to the Layer(“From”)
toComp / fromComp
convert point space to composition space
Shape Layers transform controls are relative to the composition center,
[0,0] in the shape layer space is the center of the comp [960,540].
fromComp(thisComp.layer(“from”).transform.position)
  • Add an expression to shape layer(“line”)> shape 1> Scale, to evaluate the distance between the 2 objects
length(point1,point2)
evaluates the distance between 2 points
var from = thisComp.layer(“from”).transform.position;
var to = thisComp.layer(“to”).transform.position;
[length(from,to),value[0]]
  • Add an expression to shape layer(“line”)> shape 1> Rotation, to orient the line to point to the destination object

Geometry: what is an arc tangent ?


Math.atan2(x,y) evaluates the counterclockwise angle in radians (not degrees)
between the positive X axis and the point (x, y).
radiansToDegrees() / degreesToRadians() convert angle measuring units

var from = thisComp.layer(“from”).transform.position;
var to = thisComp.layer(“to”).transform.position;
radiansToDegrees( Math.atan2( from[1]-to[1], (from[0]-to[0]) ) )-180

Because Math.atan2() evaluates counterclockwise, substract to the result 180º

  • pull out “Stroke 1” object out of “Shape 1” group and put it down in the stack, so that the stroke is rendered after transformation. You can also delete “Fill 1” object.

3. Fake Elasticity

  • Add a zigzag object under the group, change Ridges per Segment to “1” and Points to “Smooth”
  • Add an expression to shape layer(“line”)> ZigZag 1> Size, to determine the maximum size of the line and distort the line depending on the distance between the 2 layers
var from = thisComp.layer(“from”).transform.position;
var to = thisComp.layer(“to”).transform.position;
var maxd = 960; //manually adjust the maximum length
(maxd-length(from,to))/4

ZigZag works like a sinusoid, distorting in both Y and -Y

  • Add an expression to shape layer(“line”)> shape 1> Anchor Point, to shift the line position depending on the Zigzag distortion intensity
[value[0],content(“Zig Zag 1”).size]

4. Alternative routes

The oldest method around is to use Effect> Generate> Beam and link Starting / Ending Points to both layers positions. This methods can be good enough if you need only a few lines and don’t need to stylize them. But if you have more than 5 lines then render time can increase dramatically.

Motion Boutique released a while ago Connect Layers, a free script originally made as a debug tool for Plexus, that works wonders to create rendered line connectors, elastic ropes and triangulations. But you will have to re-render keyframes each time you modify the animations.

Lastly, it is worth mentioning Lines creator, a quite expensive script ($25) that automatize the method explained in this post.

DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download presets (rename .key to .zip after download) download

Bonus – Free transitions pack

Here is a pack of presets I made using expressions; it can easily be customized by duplicating groups to add more elements and automatically cycle colors (you will need the color swatch preset from previous lesson07). Expressions controls make it easy to retime, randomize and add delays. inPoint of the shape layer is being used as the start point for the time interpolation. Have fun with the freebie!

AExpr transition pack from toma ever on Vimeo.

DOWNLOAD PRESET PACK HERE
Click icon below to download presets (rename .key to .zip after download)

download

Lesson09 – Transitions

Learn how to create motion graphic transitions
REMINDER
If you are an absolute beginner, please start your learning by checking the essential resources below:
http://www.jjgifford.com/expressions/basics/index.html
https://helpx.adobe.com/after-effects/using/expression-basics.html
http://www.motionscript.com

I have seen all over the internet these graphic transitions packs for sale, sometime for prices as high as 20-30$. Why paying for it when you can make it yourself and understand how to customize it ?

1. Understand the Basic Setup

  • Shape Layers have a few built-in effector objects such as Merge Path, Repeater, Trim Paths… Great functions to create symmetries and space offsets.
  • There is no time effectors built in the Shape Layer library; we will use .valueAtTime or group indexes instead to create time delays between instances. Please review Lesson08 – Delays and Loops
  • Automate colors offset, using customized color swatches; Please review Lesson07 – Color palette

2. Cascade Strokes

  • Create a new Rectangle Shape Layer by double clicking on the Rectangle Tool in the Menu Bar
  • Rename Shape Layer> Content> Rectangle 1 to 01
  • Navigate down to Shape Layer> Content> 01> Rectangle Path 1> Size and flatten the X size
[0,thisComp.height]
  • Turn off the Fill and change the Stroke Width value to around 80 (for now)
  • Add two Repeaters in “01” Group
  • Change on the 2nd repeater Copies property to 2,
    Transform> Position to 0
    Transform> Scale to [-100, 0]
    rename the repeater to Mirror.

We will now create a link between the Composition Width Repeater and Stroke Width, so that the screen is always filled with the graphics, whatever the number of repetition is.

  • Add an expression to Shape Layer> Content> 01> Repeater 1> Transform> Position, to link the repeater position offset to the number of Copies.
var i = content(“01”).content(“Repeater 1”).copies-1;
var w = (thisComp.width/2)/i;
[w,value[1]]
  • To create a Y offset evolving over time, add a second variable
var h = easeIn(time, inPoint, inPoint + 1, -thisComp.height/i,0);
[w,h]

If we wanted the animation to last 2 seconds, we would write inPoint + 2 instead, or even create an Expression Control to adjust manually with a slider.

  • Add an expression to Shape Layer> Content> 01> Stroke 1> Stroke Width
Math.ceil(content(“01”).content(“Repeater 1”).transform.position[0])

Using Math.ceil will make the stroke size pixel perfect and avoid undesired alpha anti-aliasing problems.
Now if you adjust the repeater copies property, the graphic will adjust automatically to fill the screen with the copies.

  • Animate with a linear interpolation Shape Layer> Content> 01> Rectangle Path 1> Position, from -height to 0
linear(time, inPoint, inPoint + 1, [0,-thisComp.height], [0,0])
  • Modify this expression to add a time delay when duplicating the group
var offset = (thisProperty.propertyGroup(3).name-1)*(4/25);
linear(time, inPoint +offset, inPoint +1 +offset, [0,-thisComp.height], [0,0])

When duplicating the Group (“01”), the group name with increment of +1, adding a time delay of 4 frames in between each instances.

  • Modify the expression on Shape Layer> Content> 01> Repeater 1> Transform> Position
var offset = (thisProperty.propertyGroup(4).name-1)*(1/25);
var h = linear(time, inPoint +offset, inPoint +1.5 +offset, -thisComp.height*4/i,0);

Note I choose this animation to last 50% longer to make the cascading effect more obvious.

  • Modify the expression on Shape Layer> Content> 01> Stroke 1> Stroke Width to create gaps in between the bars that will disappear over time
var w = content(“01”).content(“Repeater 1”).transform.position[0];
Math.ceil(linear(time, inPoint, inPoint +1.5, w/2,w))
  • (Optional) Change Shape Layer> Content> Rectangle 1> Stroke 1> Line Join to Round Join
  • (Optional) Apply Xpr_swatches to the composition and xpr_colorShape to the stroke color (from Lesson07 – Color palette) to automatically cycle through colors defined in the palette.
  • Duplicate the Group (“01”) as many times as you like

3. Circular Strokes

  • Create a new Ellipse Shape Layer by double clicking on the Ellipse Tool in the Menu Bar
  • Rename Group (“Ellipse 1”) to (“01”)
  • Add an expression to Shaper Layer> 01> Ellipse Path 1> Size
var n=thisProperty.propertyGroup(4).numProperties;
var i=thisProperty.propertyGroup(3).propertyIndex;
var r=(width/n)*i;
[r,r]

That code will determine the size of each Ellipse instance; n will get how many instances are living in the same Shape Layer and i the index of that particular instance (review previous lessons if you don’t get it).

  • Add an expression to Shaper Layer> 01> Stroke 1> Stroke Width
var i=thisProperty.propertyGroup(3).propertyIndex;
var r=thisProperty.propertyGroup(3).content(“Ellipse Path 1”).size[0];
(r/(2*i))

Stroke Width will depend of the number of instances and the Size of that particular instance

  • Add an Offset Path object and add an expression to Start property
100-thisProperty.propertyGroup(3).content(“Trim Paths 1”).end
  • Add a Trim Path object and add an expression to Amount
-thisProperty.propertyGroup(3).content(“Stroke 1”).strokeWidth/2

This trick constrains the stroke inside the ellipse and creates a dohnut shape instead of an outlined stroke.

  • Add an expression to the End Property and introduce a time delay
var offset=(thisProperty.propertyGroup(3).propertyIndex-1)*2/25;
linear (time, inPoint +offset, inPoint +1 +offset, 50, 100)

That expression animates over 1 second the stroke, introducing 2 frames delay between instances

  • Modify the expression on Shaper Layer> 01> Stroke 1> Stroke Width to thicken the stroke over time and create a “filling gaps” effect
var k = linear (thisProperty.propertyGroup(3).content(“Trim Paths 1”).end, 50, 100, 0,1);
k*(r/(2*i))

this creates a multiplicator that animates doubles the size over time, following the pace of the Trim Path animation.

  • Change Shape Layer> Scale to [115,115], to fill the frame
  • (Optional) Add an expression to Shaper Layer> 01> Trim Path 1> Offset to introduce a random effector
random()
Returns a random value between 0 and 1 (or specified Max/Min values)
seedRandom(offset, timeless=false)
Random seeds are evaluated relatively to the layer indexes;
use it to offset the values but also to freeze the values in time
seedRandom(2, timeless = true);
random()*50
  • (Optional) Add 2 Effect> Expression Controls> Slider Control to manually adjust the randomization and Modify the expression
seedRandom(effect(“Random seed”)(“Slider”)+thisProperty.propertyGroup(3).name, timeless = true);
random()*effect(“Random Strength”)(“Slider”)

Note that to generate a unique seed for each instance, the number of the instance is used to automatically offset it.

  • (Optional) Apply xpr_swatches and xpr_colorShape to automatically select colors from a specified color palette
  • Duplicate the main Group as many time as desired and adjust random sliders

4. Triangles

  • Make a new Polygon Shape by double clicking ont he Polygon Tool in the menu bar
  • Change the Polygon Path points to 3 to form a triangle
  • Rename the main Group to (“01”)
  • Add an expression to Shape Layer> 01> Polygon Path 1> Radius to scale the size of the triangle to match the compostion height by

The “Outer Radius” of the triangle in After Effects
refers to the inscribed circle radius
(2/3)*thisComp.height
  • Recenter the triangle in the compo by adding an expression to Shape Layer> 01> Polygon Path 1> Position
[0,(1/6)*thisComp.height]
  • Add a Repeater in the Group
  • Change the Repeater Rotation to 180
  • Add an expression to the Position property to offset each iteration (see graphic above about relationship between radius and triangle side)
var r = thisProperty.propertyGroup(4).content(“Polystar Path 1”).outerRadius;
var a =3*r/Math.sqrt(3);
[a/2,value[1]]
  • Add an expression to the Copies property to fill the screen (see graphic above about relationship between radius and triangle side)
var r = thisProperty.propertyGroup(3).content(“Polystar Path 1”).outerRadius;
var a = 3*r/2/Math.sqrt(3);
thisComp.width/a*2
  • Add an expression to the Group (“01”) Position to offset the position to the left edge of the frame
var p = thisProperty.propertyGroup(2).content(“Polystar Path 1”).outerRadius;
[-thisComp.width/2,-thisComp.height/2+p*(3/2)]
  • Add an expression to the Group (“01”) Anchor Point to offset the position to the left edge of the frame
var r = thisProperty.propertyGroup(2).content(“Polystar Path 1”).outerRadius;
var p = thisProperty.propertyGroup(2).content(“Polystar Path 1”).position[1];
[value[0], r-p]
  • Add a second repeater under the 1st one
  • Modify the expressions on Polygon Path Radius / Polygon Path Position to scale down the triangle size depending on the number of vertical iterations
(2/3)*thisComp.height/thisProperty.propertyGroup(3).content(“Repeater 2”).copies
[0,(1/6)*thisComp.height /thisProperty.propertyGroup(3).content(“Repeater 2”).copies]
  • Add an expression on Repeater 2> Position to offset the rows down so that it fills the screen
var r = thisProperty.propertyGroup(4).content(“Polystar Path 1”).outerRadius;
var a = r*3/Math.sqrt(3);
[-1.5*a, r*3/2]

By adjusting the 2nd Repeater Copies property, it will automatically resize the whole graphic to fit the screen.

  • Change Repeater 1> End Opacity to 50%
  • To animate the graphic, modify the expression result on the 1st Repeater Copies property with a linear expression
linear(time,inPoint,inPoint+1,0,(thisComp.width/a)*2)
  • To add a time delay in between the duplicated instances, modify the expression
var offset=(thisProperty.propertyGroup(4).numProperties – thisProperty.propertyGroup(3).propertyIndex)*10/25;
linear(time,inPoint +offset,inPoint +1 +offset,0,(thisComp.width/a)*2)

To invert the time delay, so that the top layer is always the last to appear, substract the number of instances to the instance index. If we just use the group index, then the top layer wouls always be the 1st to appear, masking the other groups underneath.

  • (Optional) Add the color swatches preset and the apply xpr_colorShape to the Fill object
  • Duplicate the main Group as many time as you like.

DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download presets (rename .key to .zip after download)
download

Lesson08 – Delays and Loops

Learn how to create a looping delay / echo / cascade effect on your animation

REMINDER
If you are an absolute beginner, please start your learning by checking the essential resources below:
http://www.jjgifford.com/expressions/basics/index.html
https://helpx.adobe.com/after-effects/using/expression-basics.html
http://www.motionscript.com

1. Setup

  • Create a new Shape Layer, with a group including a path/shape and a color fill
  • Import the color swatches preset from previous lesson, and rename the layer to “colors”. Make sure no layer is selected in the timeline when importing the preset
  • Rename the group in the new Shape Layer to “01”
  • Add xpr_colorShapes preset from previous lesson to the Fill; colors are now linked to the name of the group and the color swatches. When duplicating the group, it creates a new instance using the next color.
  • Animate the position property of the Group (“01”)

2. Delay

  • Duplicate the Group (“01”) and delete the keyframes on the position property
  • Add an expression to Shape Layer> Group(“02”)> Transform> Position
  • Create a new variable to store the group name
var i = thisProperty.propertyGroup(2).name;
  • Create a new variable to store the reference Group (“01”) postion
var pos = thisProperty.propertyGroup(4).content(“01”).transform.position;

or

using the pickwhip to retrieve the path

  • Shift in time the position value
.valueAtTime(time)
Returns the value of a property at the specified time, in seconds.
pos.valueAtTime(time-(i-1))

This result will delay the second Group animation of 1 second. To change the delay influence, you can either directly add a mathematic operator to (i-1) or add an expression control for a more intuitive control over the delay

  • Route 1: mathematic operator
pos.valueAtTime(time-(i-1)*5/25)

Now the delay will only be of 5 frames (in a 25fps composition). Note that positive values will invert the delay, making the top layer coming first.

  • Route 2: expression controller; add a Effect> Expression Control> Slider Control
var delay = effect(“Slider Control”)(“Slider”);
pos.valueAtTime(time+(i-1)*delay)
  • Duplicate Group (“02”) as many times as you want and adjust Slider (“delay”) if you chose route 2

3. Built-in loop

This simpliest way to loop an animation is to use one of the loop built-in object

  • Reveal the set of keyframes on Shape Layer> Group (“01”)> Transform> Position
  • Without deleting the keyframes, add an expression to the Position property
loopIn/loopOut(type,keyframes)
use keyframes to loop on the specified interval

loopInDuration/loopOutDuration(type, duration)
use the inPoint/outPoint of the layer to loop on the specified duration

Most used types are cycle (default) and pingpong;
check built-in help for more

loopOut()

You don’t need to specify any parameter in the brackets to repeat the animation

  • Find the frame where you wish the loop to end and add a keyframe

4. Modulo loop

The built-in loop objects are most of the time enough, but they have limits; first animation needs to be most of the time precomposed, secondly, they can not coexist with other expression in a same block of code.

  • Delete the keyframes on Shape Layer> Group (“01”)> Transform> Position and replace them with a linear interpolation
linear(time, 0, 2,[-1080,0],[1080,0])

If you try to add a loop object on the next line, you will be prompted with an error message; loop object can not be added to a pre-existing block of code. But modulo (%) has no such limit, it is a basic mathematic operator that plays well with interpolations.

  • Edit the expression
linear(time%2, 0, 2,[-1080,0],[1080,0])

Every 2 seconds, the animation will loop; it would work perfectly if we did not have to take into consideration the delay. You could either adjust the loop duration manually to a value greater than the endFrame value, or create a set of new variables to get the exact delay duration.

  • Edit the expression
var delay = Math.abs(effect(“Slider Control”)(“Slider”));
var i = (thisProperty.propertyGroup(3).numProperties-1);
linear(time%(2+delay*i), 0, 2,[-1080,0],[1080,0])

by adding the delay * number of iterations, the loop matches exactly the animation length.

  • To smoothen in/out the animation, change linear to ease
ease(time, startFrame, endFrame, value1, value2)
generates a smooth interpolation
ease(time%(2+delay*i), 0, 2,[-1080,0],[1080,0])

Unfortunatety, velocity values are not accessible through expression; to get more control on the velocity, check out Ease and Wizz by Ian Haigh, a script with a nice collection of expressions that generate Expo, Circ, Quint, Quart, Quad, Sine eases, and more!

DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download presets (rename .key to .zip after download)
download

 

Lesson06 – Counter and Text Formatting

Learn how to create a counter with auto-formatting

REMINDER
If you are an absolute beginner, please start your learning by checking the essential resources below:
http://www.jjgifford.com/expressions/basics/index.html
https://helpx.adobe.com/after-effects/using/expression-basics.html
http://www.motionscript.com

1. Counter Setup

  • Create a new Text Layer
  • Add an expression to Text Layer> Text> Source Text
var num= linear(time,0,1.2,0,125000)
num
This expression animates in 1.2 seconds the counter from 0 to 125000.

2. Auto-formatting

To create a counter using the formatting $125,000.00, a few changes needs to be done.
  • Modify the variable to keep only 2 decimals
.tofixed() converts a number into a string,
keeping a specified number of decimals.
var num= linear(time,0,1.2,0,125000).toFixed(2);
num
  • Constrain the counter to always display 8 digits

while (condition) {result}
executes & accumulates a block of code
until a specified condition is satisfied.

The Meyers’ Deeper modes of expression – while:
http://provideocoalition.com/f/story/dmoe7_decisions/P3

var num= linear(time,0,1.2,0,125000).toFixed(2);
while (num.length < 9) {num = “0” + num} {num}
Our string contains 9 characters ( 8 digits, 2 decimals and a point); the condition then must be that if the string is composed of less than 9 characters, run the code until there is enough.
For example, if the value is 36.00, it will run 6 times like this:
“0”+”36.00″ = “036.00”
“0”+”036.00″ = “0036.00”

“0”+”00036.00″ = “000036.00”Remember that we are adding strings and not numbers, when
0 + 0 + 0 + 0 + 1 = 1
“0” + “0” + “0” + “0” + “1” = “00001”
  • Split the number in two with a comma
.slice(start,end: up to, but not including)
extracts part of a string
negative values select from the end of the string.
var num= linear(time,0,1.2,0,125000).toFixed(2);
while (num.length < 9) {num = “0” + num} {num};
num.slice(0,3) +”,” + num.slice(3,9)
This new result splits the string in 2 parts and glue them back together with a comma in between.
  • Add a currency symbol
“$ “+ num.slice(0,3) +”,” + num.slice(3,9)
CHECK OUT!
Dan Ebbert’s universal counter:
http://www.motionscript.com/design-guide/counter.html
DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download presets (rename .key to .zip after download) download

Lesson04 – Graphic Charts from Text File

Learn how to generate graphic charts from an external data sheet
REMINDER
If you are an absolute beginner, please start your learning by checking the essential resources below:
http://www.jjgifford.com/expressions/basics/index.html
https://helpx.adobe.com/after-effects/using/expression-basics.html
http://www.motionscript.com

1. Spreadsheet

  • Create in an empty text file series of variables using this format
bar1 = [var1, var2, var3,…];
In this example I will store [Date, Income, Volume]
bar1 = [“2000”, 153, 344]
bar2 = [“2001”, 407, 512]
bar3 = [“2002”, 241, 723]
bar4 = [“2003”, 179, 811]
bar5 = [“2004”, 226, 869]
bar6 = [“2005”, 87, 778]

2. Bar Chart

  • Back in After Effects, create a new Rectangle Shape Layer, and change the Size of the rectangle path to [100,100]
  • Rename “Group 1” to “bar1” (name of your 1st variable in the spreadsheet)
  • Add an expression to Shape Layer> Bar1> Transform> Scale
thisProperty.propertyGroup()
allows to access properties values from within a group hierarchy.
  • To access the name of the group, go back upwards 2 levels Size property> Rectangle Path1> Bar1
var myIndex = thisProperty.propertyGroup(2).name;
  • Points to your text file containing your spreadsheet
$.evalFile(“Your_absolute_path”);
  • Use the 2nd data series as the source value
var myVal = eval(myIndex)[1];
[myVal, value[1]]
  • To animate the bar, modify myVal with a linear interpolation
var myVal = linear(time, 0,1,0,eval(myIndex)[1]);
  • Add an expression to shift the position of the bar, relatively to its index number
var myIndex = thisProperty.propertyGroup(2).name;
var shift = (myIndex.substr(3,2)-1) * 110;
[value[0], shift]
The second line extracts the incrementing number from the group’s name and multiply it by the vertical size of the bar(100) + gap (10) to shift the bar position vertically.
  • To align the bars to the left, add an expression to Shape Layer> bar1> Transform> Anchor point
[-thisProperty.propertyGroup(2).content(“Rectangle Path 1”).size[0]/2,value[1]]
This expression retrieves the x size of the bar (go up 2 levels, then browses using .content objects), and shifts the anchor point negatively of half of its value
  • Duplicate “bar1” group as many times as you have created variables in the text file; your graph should build itself.

3. Delays

This expression is a simple solution to shift in time properties that follows a proportional evolution, but introducing a delay. If you apply an Effect> Time> Echo, that is the basic principle, except that our solution will bring much more control to the animation.
  • Edit the expression on Shape Layer> Bar1> Transform> Scale and replace var myVal by
var myVal = linear(time-(myIndex.substr(3,2)/5), 0,1,0,eval(myIndex)[1]);
Each iteration (bar) of the group will be shifted in time of 0.2 seconds (1/5 = 5/25 frames)

4. Labels (years)

  • Create a new Point Text Layer
  • Add an expression to Text Layer>Text> Source Text
$.evalFile(“Your_absolute_path”);
Let’s search for all the eval(myIndex)[0] (= the years stored in the text file), and add them together to create a unique string to be used as a label for the chart.
for ( starting point, how many times to run, what to do after each run)
For loop creates and processes iterations of the same expression.
MORE OPERATORS
Increment ++
Decrement
adds a value to a variable +=
subtracts a value from a variable -=
  • Add up eval(bar1)[0]+eval(bar2)[0]+…+eval(bar6)[0] = SUM eval(“bar”+i)[0].
    By running this code from value i=1 to 6 ( i<7) and after each run incrementing i (i++).
for( i=1 ; i < 7 ; i++ ) {
eval(“bar”+i)[0];
}
If we leave it as it is, it will only display the last entry; the code runs normally, but it erase each entry before displaying the new one.
  • Add strings together using the += operator to display all entries
for( i=1 ; i < 7 ; i++ ) {
myyears += eval(“bar”+i)[0]+ “\r” ;
}
myyears

Using “\r”, we also insert a line break after each entry to create a column of text instead of a line.

The “undefined” entry appears because the first time the code runs, when i = 1, the operator += tries to add to the first entry the previous entry, but there is nothing before that, hence the undefined message.

  • Use your prefered .slice .replace or .substr to delete the entry
myyears.replace(“undefined”,””)
  • Adjust font size and the paragraph spacing in the Parargraph Panel to align vertically the text with the bar spacing

5. Curve Chart

Unfortunately, we can not access vertex coordinates shape path or a mask in After Effects yet; instead, let’s draw over time the curve using the write-on effect.
  • Create a new Adjustment Layer
  • Add Effect> Generate> Write-on
  • Add an expression to Adjustment Layer> Effects> Write-on> Brush Position
$.evalFile(“your_file_path”);
var t = time;
var i = Math.floor(t+1);
Math.floor() rounds a number DOWNWARDS to the nearest integer
Math.ceil() rounds it DOWNWARDS
Variable t defines the speed of the animation
Variable i, evolve over time (t) by steps, thanks to the object Math.floor(). To synchonize time (starting at 0) and iterations (starting at 1), we’ll floor value (t+1)
  • Create 2 variables to store start position and end position
mypoint1 = [eval(“bar”+i)[1],i*110];
mypoint2 = [eval(“bar”+(i+1))[1],(i+1)*110];

X coordinates are the values stored in the text file, bar1[1] paired with bar2[1], bar2[1] with bar3[1],…
Y coordinates are multiplied by the size of a bar in the bar chart, so that both charts can be overlayed proportionnally.

  • Write a linear interpolation to drive the whole animation
linear(t,i-1,i,mypoint1, mypoint2)
An error message will appear: “property or method ‘bar7’ missing…”
The last variable stored in the text file is bar6, we need to give boundaries to the animation by giving a maximum value to i
Math.max(val1, val2,…) outputs the highest value
Math.min(val1, val2,…) outputs the lowest value
  • Modify var i
var i = Math.min(5,Math.floor(t+1));
When i reaches 5, it will stop to increment
Let’s offset the curve position and overlay it nicely to the bar chart
  • Add Effect> Expression Controls> Point Control and rename it “offset”
  • Create a new variable to store the offset point value and add it to both point variables
var offset = effect(“offset”)(“Point”);
mypoint1 = [eval(“bar”+i)[1],i*110] + offset;
mypoint2 = [eval(“bar”+(i+1))[1],(i+1)*110] + offset;
  • Move the Point Control to align the graph with the bar chart.
  • Modify var t to speed up the global animation
var t = time*5/2;
Each of the 5 point to point animation lasts for 1 second, I want to bring back this 5 seconds animation down to 2, hence *5/2
DON’T FORGET
build your own presets collection to speed up your workflow
Click icon below to download presets (rename .key to .zip after download)
download