Piet Mondrian is a modern artist best known for his grid-based abstract art. The artworks, all composed of a plane of blue, black, white, yellow, and/or red rectangles. They are well known because Mondrian was able to elicit so much visual dynamism and drama within such limiting rules. For my gif, I decided to take a Mondrian-like grid and use the looping gif to explode the grid then bring it back together.
What works? I think the concept is kind of fun, I like how Mondrian’s state is serious but then the explosion adds some whimsy. I think that I could spend more time playing with the easing to give each color additional character. I wanted to use the motion to emphasize how the white tiles were the ubiquitous background and the colored tiles were the main actors. I did this by having the whites move quickly and freeze while the colored ones smoothly animate. I’m not sure my intention is well conveyed by this combination of movement.
Sketches:
Code:
//Time variables
int fullTime;
int pause = 0;
float timeProportion;
float currentTime;
//Arrays to store the squares
Yellow[] yellowSquares;
Blue[] blueSquares;
White[] whiteSquares;
Red[] redSquares;
Black[] blackSquares;
//Constants for the easing functions
float a = .467;
float b = .660;
float c = .0;
//variable for the PatternMaster. Not actually used in this script
String functionName;
//Debug Boolean to turn on and off recording and to turn on and off animation
boolean recording = true;
boolean animation = true;
void setup() {
frameRate(3);
size(1500,938);
fullTime = 10;
currentTime = 0;
yellowSquares = new Yellow[8];
blueSquares = new Blue[3];
whiteSquares = new White[24];
redSquares = new Red[3];
blackSquares = new Black[6];
createShapes();
}
//Where all the shapes are created.
void createShapes() {
yellowSquares[0] = new Yellow(.02,25,568,112,236);
yellowSquares[1] = new Yellow(.02,512,22,235,82);
yellowSquares[2] = new Yellow(.02,512,114,235,171);
yellowSquares[3] = new Yellow(.02,330,751,74,174);
yellowSquares[4] = new Yellow(.02,758,657,231,169);
yellowSquares[5] = new Yellow(.02,1003,22,78,78);
yellowSquares[6] = new Yellow(.02,1003,114,170,76);
yellowSquares[7] = new Yellow(.02,1367,114,111,262);
blueSquares[0] = new Blue(.02,760,27,232,169);
blueSquares[1] = new Blue(.02,1005,477,350,350);
blueSquares[2] = new Blue(.02,512,568,237,174);
redSquares[0] = new Red(.02,148,112,345,347);
redSquares[1] = new Red(.02,756,206,231,165);
redSquares[2] = new Red(.02,510,749,230,168);
blackSquares[0] = new Black(.02,147,476,170,170);
blackSquares[1] = new Black(.02,329,659,172,80);
blackSquares[2] = new Black(.02,881,840,109,79);
blackSquares[3] = new Black(.02,1185,296,171,169);
blackSquares[4] = new Black(.02,1004,205,167,81);
blackSquares[5] = new Black(.02,1094,23,81,78);
whiteSquares[0] = new White(.02,23,22,169,76);
whiteSquares[1] = new White(.02,207,23,290,75);
whiteSquares[2] = new White(.02,1187,23,291,78);
whiteSquares[3] = new White(.02,25,113,110,168);
whiteSquares[4] = new White(.02,1186,112,166,168);
whiteSquares[5] = new White(.02,24,293,109,260);
whiteSquares[6] = new White(.02,512,294,108,170);
whiteSquares[7] = new White(.02,633,294,108,170);
whiteSquares[8] = new White(.02,511,478,233,76);
whiteSquares[9] = new White(.02,1004,297,164,74);
whiteSquares[10] = new White(.02,1002,386,172,75);
whiteSquares[11] = new White(.02,1368,386,107,259);
whiteSquares[12] = new White(.02,1365,659,113,170);
whiteSquares[13] = new White(.02,1309,843,166,75);
whiteSquares[14] = new White(.02,1005,839,289,78);
whiteSquares[15] = new White(.02,420,749,75,168);
whiteSquares[16] = new White(.02,330,568,169,76);
whiteSquares[17] = new White(.02,148,656,165,171);
whiteSquares[18] = new White(.02,331,477,166,76);
whiteSquares[19] = new White(.02,880,477,111,169);
whiteSquares[20] = new White(.02,757,476,111,169);
whiteSquares[21] = new White(.02,757,386,233,79);
whiteSquares[22] = new White(.02,24,840,291,78);
whiteSquares[23] = new White(.02,757,840,110,77);
}
void draw() {
if(animation) {
updateTime();
} else {
currentTime = 1;
}
drawBackground();
drawShapes();
if(recording) {
saveFrame();
}
}
//function to control the time. I've inserted a pause after each transition
void updateTime() {
currentTime++;
if(currentTime > (fullTime+pause)) {
recording = false;
currentTime = 0;
} else if (currentTime == (fullTime)) {
currentTime = fullTime;
}
timeProportion = currentTime/fullTime;
if(timeProportion > 1) { timeProportion = 1; }
}
void drawBackground() {
background(40);
}
void drawShapes() {
for(int i = 0; i < whiteSquares.length; i++) {
whiteSquares[i].update();
}
for(int i = 0; i < yellowSquares.length; i++) {
yellowSquares[i].update();
}
for(int i = 0; i < blueSquares.length; i++) {
blueSquares[i].update();
}
for(int i = 0; i < redSquares.length; i++) {
redSquares[i].update();
}
for(int i = 0; i < blackSquares.length; i++) {
blackSquares[i].update();
}
}
//An example of the Yellow class. I'm excluding the other classes to save space.
//They all function similarly.
class Yellow {
int x;
int y;
int w;
int h;
int direction;
int leftRight;
float comeIn = random(1);
int magnitude = 0;
float shadowDepth = 5;
Yellow (float _wait, int _x, int _y, int _w, int _h) {
x = _x;
y = _y;
h = _h;
w = _w;
direction = (int) random(2);
leftRight = 0;
if (random(1) > .5) {
leftRight = -1;
} else {
leftRight = 1;
}
shadowDepth += random(10);
magnitude = (int) random(10) + 12;
}
void update() {
pushMatrix();
noStroke();
float easePoint = ease(timeProportion, a, b) ;
float newX = x;
float newY = y;
if(direction == 1) {
newX = x + leftRight*magnitude*easePoint;
newY = y + leftRight*magnitude*easePoint;
} else {
newX = x - leftRight*magnitude*easePoint;
newY = y - leftRight*magnitude*easePoint;
}
translate(newX, newY);
fill(250,223,23,40);
float shadowOffset = easePoint*shadowDepth;
rect(shadowOffset,shadowOffset,w,h);
fill(250,223,23);
rect(0,0,w,h);
popMatrix();
}
}