https://editor.p5js.org/ssahasra/present/mf6vOSPgw
The idea was to correlate temparatures and COVID cases of two months far apart from each other in the year 2020.
I used arrays to fill in the values of the number of cases (height of bar) with loops and used the buttons [mouse interactions] and array, objects to create effects of different weather conditions. For some of the weather effects I sourced code from current projects on the internet.
After receiving feedback on my proposal, I made two key changes:
1. Instead of using files to load data I added the values to indices of an array, to create a data visualization + monthly calendar that shows the number of COVID cases
2. I made it more relevant to the theme of 2020. Earlier I was working only with temperature data, but now I decided to represent the relationship between temperature and COVID cases.
The central idea of my projects is to create an interactive visualization + calendar that allows the viewer to compare different months of the year and see how temperature affects the rise in COVID cases (although there are of course other factors for the rise) Furthermore, I want to use mouse interactions to filter certain days when temperatures are in particular range using the buttons on the right (see diagram and code). I am still in the process of adding interactivity and controls using the <function mousePressed()> Optionally, a hover state over one or two of the bars (if time permits, to show the temperature and number of COVID cases to make it a more realistic visualisation)
When the button is pressed, some bar graphs that are not in that temperature range, will disappear and I want to use random motion, I learnt in class to create effects of snow, rain, sun etc in the background of each month. If I am successful in this, as a next step, I would also like to add sound files that create sound effects along with the visual effects of the weather. For the visual effects, my plan is to use the code I used for the snow and change parameters, color, speed etc, to create the other weather effects. For examples: raindrops will be blue and would sway less, and fall down in straighter lines than snow.
Below is the code snippet for the entire final program:
let lastFramePress = false;
let toggle = false;
let value = 0;
let button;
let snowflakes = []; // array to hold snowflake objects
let rain = [];
let snow ;
mayCases = [1540, 1307, 1008, 913, 975, 1022, 1160, 1352, 1160,
1376, 520, 850, 787, 964, 1020, 1050, 517, 931, 728,
747, 1101, 1053, 797, 554, 700, 517, 773, 666, 761, 716, 429]
mayMidTempCases = [0, 1307, 1008, 0, 0, 0, 1160, 0, 0,
1376, 0, 0, 787, 964, 0, 1050, 0, 931, 728,
747, 1101, 1053, 797, 0, 0, 0, 0, 0, 761, 716, 429] //on high temparature days
mayHighTempCases = [0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1020, 0, 517, 0, 0,
0, 0, 0, 0, 554, 700, 517, 773, 666, 761, 716, 429] //on mid temparature days
mayLowTempCases = [1540, 0, 0, 913, 975, 1022, 0, 1352, 1160,
0, 520, 850, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //on low temparature days
novCases = [2815, 3648, 3236, 2580, 4562, 4322, 4098, 6023,
5834, 4395, 4647, 6241, 5721, 6486, 6881, 7028,
5874, 6541, 6462, 6365, 6956, 7427, 8362, 6883,
5144, 5584, 6956, 8654, 11268, 5000]
novHighTempCases = [0, 0, 3236, 2580, 4562, 4322, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]
novMidTempCases = [2815, 3648, 0, 0, 0, 0, 4098, 6023,
0, 0, 4647, 0, 0, 0, 6881, 7028,
5874, 6541, 0, 0, 0, 7427, 8362, 6883,
0, 5584, 0, 0, 0, 0]
novLowTempCases = [0, 0, 0, 0, 0, 0, 0, 0,
0, 4395, 0, 6241, 5721, 6486, 0, 0,
0, 0, 6462, 0, 6956, 0, 0, 0,
5144, 0, 6956, 8654, 11268, 5000]
function preload() {
cloud = loadImage('https://i.imgur.com/MsvLwqH.png');
snowFlake = loadImage('https://i.imgur.com/wvzYocn.png');
sun = loadImage('https://i.imgur.com/AGRTqDm.png');
}
function setup() {
//star-size
let SWH1 = random(2, 8);
let SWH2 = random(6, 10);
let SWH3 = random(10, 13);
background(51,59,68);
createCanvas(1300, 900);
button = createButton("☀️");
button.mousePressed();
button.position(1180, 90);
button.size(50,50);
button.style('font-size', '25px');
button = createButton("☁️");
button.mousePressed();
button.position(1180, 160);
button.size(50,50);
button.style('font-size', '25px');
button = createButton("❄️");
button.mousePressed();
button.position(1180, 230);
button.size(50,50);
button.style('font-size', '25px');
}
function draw() {
background(51,59,68);
fill(255);
textSize(12);
text ('M A Y : C O V I D C A S E S', 50, 80);
text ('N O V E M B E R : C O V I D C A S E S', 50, 780);
textSize(21);
text ('D o C O V I D C a s e s I n c r e a s e W h e n T e m p ar a t u r e s L o w e r ?', 50, 840, 900, 60);
strokeWeight(3.2);
fill(255,10);
noStroke();
rect(50,80,width-200,320);
rect(50,450,width-200,320);
translate(30,50);
fill(255, 80);
may();
fill(255,0,0,80);
november();
calendar();
//sunrays();
rainfall();
noStroke();
fill(255);
//mayHigh();
mousePressed();
fill(255,10);
rect(1137, 27, 60, 60);
rect(1137, 97, 60, 60);
rect(1137, 167, 60, 60);
}
function calendar() {
fill(51,59,68);
for (let i=0;i<31;i++) {
let index = i + 1;
//stroke(255, 50);
push();
fill(255);
noStroke();
textSize(12);
text(index, i*(245/7)+38, 380);
pop();
}
}
//____////____////____////____////____////____////____////____////____////____////____////____//
function createSnowflake() {
// create a random number of snowflakes each frame
let t = frameCount / 60; // update time
for (let i = 0; i < random(5); i++) {
fill(255);
snowflakes.push(new snowflake()); // append snowflake object
}
// loop through snowflakes with a for..of loop
for (let flake of snowflakes) {
flake.update(t); // update snowflake position
flake.display(); // draw snowflake
}
}
function snowflake() {
//referenced from the p5.js open source examples
// initialize coordinates
this.posX = 0;
this.posY = random(-50, 0);
this.initialangle = random(0, 2 * PI);
this.size = random(2, 5);
// radius of snowflake spiral
// chosen so the snowflakes are uniformly spread out in area
this.radius = sqrt(random(pow(width / 2, 2)));
this.update = function(time) {
// x position follows a circle
let w = 0.6; // angular speed
let angle = w * time + this.initialangle;
this.posX = width / 2 + this.radius * sin(angle);
// different size snowflakes fall at slightly different y speeds
this.posY += pow(this.size, 0.5);
// delete snowflake if past end of screen
if (this.posY > height) {
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
};
this.display = function() {
ellipse(this.posX, this.posY, this.size);
}
}
//____////____////____////____////____////____////____////____////____//
function createRain() {
// create a random number of snowflakes each frame
let t = frameCount / 60; // update time
for (let i = 0; i < random(5); i++) {
fill(255);
rain.push(new rainfall()); // append snowflake object
}
// loop through snowflakes with a for..of loop
for (let drop of rain) {
drop.update(t); // update snowflake position
drop.display(); // draw snowflake
}
}
function rainfall() {
this.posX = 10;
this.posY = random(0, width);
this.initialangle = random(0, PI);
this.size = random(4, 20);
// radius of snowflake spiral
// chosen so the snowflakes are uniformly spread out in area
this.radius = sqrt(random(0,1000), 1);
this.update = function(time) {
// x position follows a circle
let w = 1; // angular speed
let angle = w * time + this.initialangle;
this.posX = width / 35 + 1000 * sin(angle); // change this angle for rain
// different size snowflakes fall at slightly different y speeds
this.posY += pow(this.size, 5);
// delete snowflake if past end of screen
if (this.posY > 260) {
let index = rain.indexOf(this);
rain.shift(index, 3);
}
}
this.display = function() {
ellipse(this.posX, this.posY, this.size);
}
}
//____////____////____////____////____////____////____////____////____////____//
function sunrays() {
rays = random(280, 650);
//stars in the universe
fill(250, 200, 0);
ellipse(mouseX*1.1, mouseY*1.8, random(2, 8), random(2, 8));
ellipse(mouseX*1.3, mouseY*2.5, random(6, 10), random(6, 10));
ellipse(mouseX*2.3, mouseY*1.5, random(10, 13), random(10, 13));
ellipse(mouseX/1.1, mouseY/1.8, random(2, 8), random(2, 8));
ellipse(mouseX/1.3, mouseY/2.5, random(6, 10), random(6, 10));
ellipse(mouseX/2.3, mouseY/1.5, random(10, 13), random(10, 13));
//glow
fill(200, 130, 10, 20);
ellipse(0, 0, (frameCount % 500)*2, (frameCount % 500)*2);
ellipse(0, 0, (frameCount % 500)*4, (frameCount % 500)*4);
ellipse(0, 0, (frameCount % 500)*8, (frameCount % 500)*8);
ellipse(0, 0, (frameCount % 500)*16, (frameCount % 500)*16);
ellipse(0, 0, (frameCount % 500)*24, (frameCount % 500)*24);
//sun
fill(250, 200, 0);
ellipse(5, -11, rays - 20, rays - 30);
}
function may() {
for (var i=0; i <= mayCases.length; i++) {
fill(255, 99);
rect((i*35+3)+25,350,33,-mayCases[i]*0.035);
//ellipse((i*35+3)+25,190,-mayCases[i]*0.035);
}
if (mayCases[i]*0.25 >= 20) {
fill(255, 99);
}
}
function mayHigh() {
for (var i=0; i <= mayHighTempCases.length; i++) {
fill(255,99);
rect((i*35+3)+25,350,33,-mayHighTempCases[i]*0.035);
}
if (mayHighTempCases[i]*0.25 >= 20) {
fill(255,0,0,99);
}
}
function mayMid() {
for (var i=0; i <= mayMidTempCases.length; i++) {
fill(255,99);
rect((i*35+3)+25,350,33,-mayMidTempCases[i]*0.035);
}
if (mayMidTempCases[i]*0.25 >= 20) {
fill(255,99);
}
}
function mayLow() {
for (var i=0; i <= mayLowTempCases.length; i++) {
fill(255,99);
rect((i*35+3)+25,350,33,-mayLowTempCases[i]*0.035);
}
if (mayLowTempCases[i]*0.25 >= 20) {
fill(255,0,0,99);
}
}
function november() {
for (var i=0; i <= novCases.length; i++) {
rect((i*35+3)+25,400,33,novCases[i]*0.035);
//ellipse((i*35+3)+25,560,-novCases[i]*0.035);
}
}
function novLow() {
for (var i=0; i <= novLowTempCases.length; i++) {
fill(255,0,0,99);
rect((i*35+3)+25,400,33,novLowTempCases[i]*0.035);
//ellipse((i*35+3)+25,560,-novCases[i]*0.035);
}
if (novLowTempCases[i]*0.25 >= 20) {
fill(255,0,0,99);
}
}
function novMid() {
for (var i=0; i <= novMidTempCases.length; i++) {
fill(255,0,0,99)
rect((i*35+3)+25,400,33,novMidTempCases[i]*0.035);
//ellipse((i*35+3)+25,560,-novCases[i]*0.035);
}
if (novMidTempCases[i]*0.25 >= 20) {
fill(255,0,0,99);
}
}
function novHigh() {
for (var i=0; i <= novHighTempCases.length; i++) {
fill(255,0,0,99);
rect((i*35+3)+25,400,33,novHighTempCases[i]*0.035);
//ellipse((i*35+3)+25,560,-novCases[i]*0.035);
}
if (novHighTempCases[i]*0.25 >= 20) {
fill(255,0,0,99);
}
}
function mousePressed() {
//rect(1137, 27, 60, 60);
//rect(1137, 97, 60, 60);
//rect(1137, 167, 60, 60);
if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 40 && mouseY <= 110) {
mayHigh();
novHigh();
sunrays();
} else if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 110 && mouseY <= 180) {
mayMid();
novMid();
createRain();
} else if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 200 && mouseY <= 250) {
mayLow();
novLow();
createSnowflake();
}
}
]]>It seems in my experience, wallpaper gets a bad reputation. One quick search of “interior design” on Pinterest will reveal the modern day obsession with sleek and minimal aesthetic choices. In the face of this, I chose to design a wallpaper that riffs off of aesthetic choices perhaps equally as brawny – inspired by the loud colors of post modernism.
// JUBBIES STEINWEH-ADLER
// PROJECT 05 - GROOVY WALLPAPER
// SECTION D
//GLOBAL VALUES
x = 0;
y = -150;// initial y value off canvas to create seamless pattern
d = 0; // arrow direction ( 1 = left 0 = right )
function setup() {
createCanvas(500, 400);
background(250, 240, 220);
blendMode(MULTIPLY); // color blend mode multiplies rgb value of overlapping colors
}
function draw() {
//ROW PROPERTIES
for(var loop = 0; loop < 5; loop +=1) { // number of total rows limited to 5
if (d == 0) { //switching direction for each loop
d = 1; //left arrows
} else {
d = 0; //right arrows
}
//TRIANGLE PROPERTIES
for(var row = 0; row < 1; row +=1) { // triangle x-offset and tracking
x = -120; // initial x value for the first triangle
y += 110; // vertical spacing, tracking
for(var rep = 0; rep < 7; rep +=1) {
x += 120; // distance between each module (width)
stack(d, x, y);
}
}
}
noLoop(); //disables automatic looping from draw function
}
// TRIANGLE PACKAGE - Grouped for single 'anchor point'
function stack(d, x, y) {
push();
translate(x, y); // translate by determined x and y value
module(d); // draw a single triangle module
pop();
}
//TRIANGLE MODULE DRAW COMMAND
function module(d) {
noStroke();
var r = 180; //red value
var g = 40; //green value
var b = 190; //blue value
//RIGHT ARROW MODULE
if (d == 0){
px = 0; //linked X coordinate
py = 0; //linked y coordinate
//vertical leg
fill(r, g, b);
push();
translate(px, py);
rect(0, 0, 50, 170, 70);
pop();
//top angled leg
fill(g, b, r);
push();
translate(px-10, py+35);
rotate(radians(300));
rect(0, 0, 50, 170, 70);
pop();
//bottom angled leg
fill(b, r, g);
push();
translate(px+15, py+180);
rotate(radians(240));
rect(0, 0, 50, 170, 70);
pop();
//LEFT ARROW MODULE
} else if (d == 1) {
fill(r, g, b);
ptO = 60; // OFFSET VALUE TO ALTERNATE ROW START POSITION
ptT = 0;
//vertical leg
push();
translate(ptO, ptT);
rect(0, 0, 50, 170, 70);
pop();
//top leg
fill(g, b, r);
push();
translate(ptO +35, ptT - 10);
rotate(radians(60));
rect(0, 0, 50, 170, 70);
pop();
//bottom leg
fill(b, r, g);
push();
translate(ptO + 60, ptT + 135);
rotate(radians(120));
rect(0, 0, 50, 170, 70);
pop();
}
}
For the actual pattern shape, I was inspired by this pattern I found on the internet. I really enjoyed how the colors interacted where the shapes overlapped. This pushed me to discover that p5.js has blending modes. Using multiply blending mode and adjusting the opacity is how I got my final result.
]]>I really admire the video game “Panoramical” by Fernando Ramallo and David Kanaga. It is a very beautiful and immersive experience through a world of stunning visuals and music. The landscapes and music inside the game change based on the player’s input.
I admire this work of generative art because of its beauty and interactivity. To put it bluntly, a lot of computer generated artworks have interesting concepts but are lacking in the quality of experience they provide. “Panoramical” on the other hand draws you in with otherworldly visuals and sounds. It is otherworldly due to the usage of algorithms, but it is beautiful due to the creators’ sensibilities to colors and sound. Each landscape and how they change is designed with care, and the music is designed to immerse players into the landscape.
“Panoramical” stands out from motion graphics and animated experiences due to its interactivity. Thanks to the creators’ usage of algorithms to “connect multiple sensory variables to [the player’s] actions” (1), the player actively becomes a part of the experience.
I think “Panoramical” is a good example of how the infinite possibilities of algorithms working inside the bounds of an artist’s design can create an unique and beautiful experience.
Work Cited
“This Person Does Not Exist” is a computational project that was created by Phillip Wang using StyleGAN, a machine learning framework made available by the technology company Nvidia. Phillip is a former Uber software engineer who created the program to show the impressive capabilities of GANs (generative adversarial networks.) It was originally shared to a small Facebook group but went on to get over 4 million hits. His inspiration for the project likely came from the rise of intelligent video manipulation and “deepfakes” on the internet.
Upon loading the webpage, the screen is filled with a high definition headshot of a random person. Reloading the page brings up another person, and so on. While the images look believable, they are all completely fabricated by an artificial intelligence; thus the title “This Person Does not Exist.”
What makes this project so interesting to me is the questions it brings up. If a computer program can so easily trick us into thinking a face is real, what else could we be made to believe? In a world where we already question almost every piece of information fed to us from entertainment media and the news, it seems as though tools for digital deception are only becoming more advanced. By highlighting the exponentially expanding capabilities of artificial intelligence, this work leaves the user feeling both deep discomfort and utter awe.