Animated Data: Excess
This animated GIF was originally meant to be a flip-book, although with Covid-19 returning to NZ, and resources to make a flip-book becoming difficult to access, we decided to just complete the animation and remove the flip-book element of it. I titled this animation “Excess” as it represented excess food being wasted and rotting away.
The original black square represents the total food produced each year, which is “eaten” and “consumed” by humanity. I decided on white circles, as their randomly generated placement creates a unique “organic” feel to the removing of the black. Additionally, white is associated with negative space, and so placing a white object on a black object creates the illusion of having eaten away at that black object.
Once we get to the point that 1/3 of the “food” is left, that rots and falls away, leaving “fumes” behind that dissipate, revealing the statistic the animation was based on.
I decided the font based on testing with various fonts and seeing which ones where easiest to read despite the “fumes” covering parts of it.
For more details on the process behind this animation, see this blog post.
/* "Excess" by Melody Elwood
* Made in Proccessing 3.5.4
* V5 published on 21/08/2020
*/
//Imports
import fisica.*;
//CONSTANTS ********************************
int END_FRAMES = 60;
int MAX_FRAMES = 300;
int FRAME_RATE = 10;
int END_FRAME_RATE = 60;
int COUNT_STEP = 15; //12 [15]
int SIZE = 5; //10 [5]
int SIZE_ERROR = 5; //3 [5]
float DOT_MULTIPLIER = 2.5; //1 [2.5]
float GRAVITY = 400;
float DENSITY = 10;
float VELOCITY_DOWN = 400;
int NUM_WASTE_BALLS = 1100;
int WASTE_SIZE_INCREASE = 7;
//CONSTANTS END ***************************
//Global variables
PFont font;
int count = 0;
int rot_size; //313
FWorld world;
void setup() {
//setup basic frame
size(700, 700);
background(255);
frameRate(FRAME_RATE);
//setup rot size
rot_size = height-((height-20)/3)-20;
//setup font
String[] fontList = PFont.list();
printArray(fontList);
font = createFont("SansSerif.bold", 24);
//set random seed for reproducibility
randomSeed(22);
//initiate the Fisica world
Fisica.init(this);
world = new FWorld();
world.setGravity(0, GRAVITY);
//Draw the inital square
fill(0);
rect(20, 20, width-40, height-40);
}
void draw() {
//Set stroke and fill to white
stroke(255);
fill(255);
//For an ever increasing number of dots, randomly place them within the allowed area
//I used random placement as it created a more "organic consumption" look, without me needing to specify where to place the thousands of dots
for (int i = 0; i < count*DOT_MULTIPLIER; i++) {
float size = SIZE+random(-SIZE_ERROR, SIZE_ERROR);
float x = random(width);
float y = random(20, (height-20)-((height-20)-count)-size);
//Make sure none end up in the "rot" area
if (y >= rot_size)
{
y = random(20,(((height-20)/3)+((height-20)/3))-size);
}
//create the dot
circle(x, y, size);
}
//Increase the number of dots and how far along they can be
count+=COUNT_STEP;
//Because we're no longer working with flipbooks, I can have much more control over timing
if(frameCount+1 == END_FRAMES)
{
frameRate(1); //Give the last frame before dropping a bit of hang time
}
else if (frameCount == END_FRAMES) { //If it's entering into the ending
frameRate(END_FRAME_RATE);
//Create all the "rot" dots
for (int i = 0; i < NUM_WASTE_BALLS; i++) {
float size = SIZE+random(-SIZE_ERROR, SIZE_ERROR) + WASTE_SIZE_INCREASE;
float x = random(20, width-20);
float y = random((((height-20)/3)+((height-20)/3)),height-20);
//Create them into the Fisica world
FCircle waste = new FCircle(size);
waste.setPosition(x,y);
waste.setDensity(DENSITY);
waste.setVelocity(0, VELOCITY_DOWN);
waste.setDamping(0.0);
waste.setNoStroke();
waste.setFill(0);
world.add(waste);
}
//Start the physics by runing it through one step
world.step();
world.draw();
//Allow white dots to be placed anywhere
rot_size = height;
}
else if (frameCount > END_FRAMES) {
//Run the ball drop sim
world.step();
world.draw();
}
//always print the text over everything (Hidden by the black to start)
textFont(font);
textAlign(CENTER);
fill(0);
text("Each year 1/3 of all food produced ends up rotting", width/2, height-(height-20)/3+10);
text("in the bins of consumers and retailers, or spoiling", width/2, height-(height-20)/3+34);
text("due to poor transportation and harvesting practices.", width/2, height-(height-20)/3+58);
//Absolute end
if (frameCount > MAX_FRAMES)
{
//Stop the program
frameRate(0);
println("END");
}
//Save each fram to make it into a GIF later
saveFrame("frame-######.png");
}