xxxxxxxxxx
195
/*
Weather Data Visualization - Sean Kennedy
This idea for this project is that the application is unreliable. While the data it delivers is accurate, the projections it makes about that data are not. Yes, it is 75 degrees outside, but no, that is not "boiling hot." This functions as a sort of interactive joke that hopefully creates a humorous response to something as mundane as the weather.
Some code is copied from the in class JSON example, that is marked with a comment CC meaning "Copied Code." Any code from other locations will be marked as well but with the specific source.
*/
var temps= [];
var cloudcover = [];
var dates= []; // these arrays will contain our temperatures, cloudiness and their corresponding dates
var x,tox,w,tow // Copied from https://gist.github.com/companje/5478fff07a18a1f4806df4cf77ae1048
function preload(){
jsonData = loadJSON('https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/weatherdata/forecast?aggregateHours=24&combinationMethod=aggregate&contentType=json&unitGroup=us&locationMode=single&key=ZRS4RFJ9TLXRRU766U6YXXKM2&dataElements=default&locations=Denver%2C%20CO%2C%20US', 'json')
} // CC
function setup() {
createCanvas(600, 600);
w = tow = window.innerWidth;
x = tox = w / 2; // copied code from that github link above, for the left and right panning.
let dateOptions = {weekday: 'long', month: 'long', day: 'numeric'}; //CC'
temps[0] = jsonData.location.currentConditions.temp // set today's temperature first
let today = new Date(jsonData.location.values[1].datetime) // get today's date
dates[0] = today.toLocaleString('en-US', dateOptions);
cloudcover[0] = jsonData.location.values[0].cloudcover;
for (let i = 2; i<9; i++){ // 7 day forecast
let entry = jsonData.location.values[i]; //CC
let date = new Date(entry.datetime);//CC
let dateLabel = date.toLocaleString('en-US', dateOptions);//CC
//print(jsonData.location.values[i].temp + " " + dateLabel); this was in here for debug purposes
temps[i-1] = jsonData.location.values[i].temp;
dates[i-1] = dateLabel;
cloudcover[i-1] = jsonData.location.values[i].cloudcover
// fill the temps clouds and dates with data or the arrays. i-1 because the numbering in the Json data starts with today at position 1, but we need today at position 0, and so on
//print(jsonData)
//print(temps)
//print(dates)
} // end for
} // end setup
function draw() {
if (minute() == 59 && second() == 59){ // update current temp every hour
temps[0] = jsonData.location.currentConditions.temp
print("updated!")
}
background(color('#B8DBD9')); // sky blue
noStroke()
let pan = constrain(tox, -3777.5, 425.5 ) // constrain the pan so you can't scroll off screen, this does create an issue though where the tox variable does continue, which can make the program unresponsive. Not sure how to fix that.
//print(tox)
translate(pan - 425, 0) // the -425 just sets today as the starting point
for (let i = 0; i < 15; i++){ // for loop that draws some clouds across the screen
let x = map(i,0, 15,0, width * 9);
clouds(x,-30,2948 + i);
clouds(x - 419,0,83982 + i);
}
blendMode(MULTIPLY)
rectMode(CORNER)
fill(color('#2F4550')) // dark blue
rect(0, 25, width * 8, 50); // top dark bar
for (let i = 0; i <=7; i++){ // for each day...
blendMode(BURN)
fill(color('#2F4550')) // medium blue
rectMode(CENTER)
rect(width/2 + (width* i),height/4 + 50,420,200) // background for temperatures
blendMode(BLEND)
textAlign(CENTER)
let fontSize = 160
textSize(fontSize)
fill(0, 70)
text(temps[i] + "°",width/2 - 5 + (width * i),height/4 + 50 + fontSize/3 + 3) // temp display
fill(color('#F4F4F9')) // white blue
text(temps[i] + "°",width/2 + (width * i),height/4 + 50 + fontSize/3) // called twice to create a drop shadow
textSize(18)
text(dates[i], width/2 + (width * i), 50 + 18/3)
textSize(30)
push()
translate(0,-30) // translates because I was lazy and didn't want to manually move each cloud description text up, but this helps a lot by basically centering on the cloud
// these are the conditionals for cloud cover, which comes as a number, and the interpretation, which is accurate, of them.
if (cloudcover[i] < 5){
fill(0,70)
text("Clear Skies.", width/2 + (width * i) - 2, height - 40 + 2)
fill(color('#4B7F89'))
text("Clear Skies.", width/2 + (width * i), height - 40)
} else if (cloudcover[i] >= 5 && cloudcover[i] <= 10) {
fill(0,70)
text("Partly Cloudy.", width/2 + (width * i) - 2, height - 40 + 2)
fill(color('#4B7F89'))
text("Partly Cloudy.", width/2 + (width * i), height - 40)
} else if (cloudcover[i] >= 11 && cloudcover[i] <= 15) {
fill(0,70)
text("Pretty Cloudy.", width/2 + (width * i) - 2, height - 40 + 2)
fill(color('#4B7F89'))
text("Pretty Cloudy.", width/2 + (width * i), height - 40)
} else if (cloudcover[i] > 15 && cloudcover[i] <= 20) {
fill(0,70)
text("Canopy of Clouds.", width/2 + (width * i) - 2, height - 40 + 2)
fill(color('#4B7F89'))
text("Canopy of Clouds.", width/2 + (width * i), height - 40)
} else if (cloudcover[i] > 20) {
fill(0,70)
text("Chance of Rain.", width/2 + (width * i) - 2, height - 40 + 2)
fill(color('#4B7F89'))
text("Chance of Rain.", width/2 + (width * i), height - 40)
}
pop()
// below is how we determine which text to display, and how to interpret the temperature given to you. Of course, the entire joke being that these interpretations are inaccurate.
if (temps[i] >=32 && temps[i] <= 45){
textSize(100)
fill(0, 50)
text("Phew!", width/2 - 5 + (width * i), height/3 * 2 + 3)
fill(color('#2F4550'))
text("Phew!", width/2 + (width * i), height/3 * 2)
fill(0, 50)
textSize(30)
text("It's hot out there!", width/2 - 2 + (width * i), height/3 * 2 + 50 + 2)
fill(color('#2F4550'))
text("It's hot out there!", width/2 + (width * i), height/3 * 2 + 50)
} else if (temps[i] > 45 && temps[i] <= 50) {
textSize(100)
fill(0, 50)
text("Ahhhh!", width/2 - 5 + (width * i), height/3 * 2 + 3)
fill(color('#2F4550'))
text("Ahhhh!", width/2 + (width * i), height/3 * 2)
fill(0, 50)
textSize(30)
text("The Earth is melting!", width/2 - 2 + (width * i), height/3 * 2 + 50 + 2)
fill(color('#2F4550'))
text("The Earth is melting!", width/2 + (width * i), height/3 * 2 + 50)
} else if (temps[i] > 50 && temps[i] <= 60) {
textSize(100)
fill(0, 50)
text("Beware!", width/2 - 5 + (width * i), height/3 * 2 + 3)
fill(color('#2F4550'))
text("Beware!", width/2 + (width * i), height/3 * 2)
fill(0, 50)
textSize(30)
text("It's colder than Mars outside!", width/2 - 2 + (width * i), height/3 * 2 + 50 + 2)
fill(color('#2F4550'))
text("It's colder than Mars outside!", width/2 + (width * i), height/3 * 2 + 50)
} else if (temps[i] > 60 && temps[i] <= 70) {
textSize(100)
fill(0, 50)
text("Danger!", width/2 - 5 + (width * i), height/3 * 2 + 3)
fill(color('#2F4550'))
text("Danger!", width/2 + (width * i), height/3 * 2)
fill(0, 50)
textSize(30)
text("You will burn out there!", width/2 - 2 + (width * i), height/3 * 2 + 50 + 2)
fill(color('#2F4550'))
text("You will burn out there!", width/2 + (width * i), height/3 * 2 + 50)
} else if (temps[i] > 70){
textSize(100)
fill(0, 50)
text("Brrrrrr!", width/2 - 5 + (width * i), height/3 * 2 + 3)
fill(color('#2F4550'))
text("Brrrrrr!", width/2 + (width * i), height/3 * 2)
fill(0, 50)
textSize(30)
text("Bundle up, it's cold!", width/2 - 2 + (width * i), height/3 * 2 + 50 + 2)
fill(color('#2F4550'))
text("Bundle up, it's cold!", width/2 + (width * i), height/3 * 2 + 50)
}
}
}
function clouds(xCoor, yCoor, offset){
push();
translate(xCoor, yCoor);
translate(0, height- 50);
let cloudCount = map(cloudcover[0], 0, 20, 0, 100) // cloudiness of the app is based on the cloudiness of real life.
for (let i = 0; i < cloudCount; i++) {
translate(3, 0)
let diam = map(noise(i), 0, 1, 30, 100);
let y = map(noise(i + offset), 0, 1, -100, 100)
fill(255,90)
ellipse(i * 3 ,y, diam, diam);
}
pop();
}
function mouseDragged(){ // copied from https://gist.github.com/companje/5478fff07a18a1f4806df4cf77ae1048
tox += constrain(mouseX-pmouseX,-1971.5, 425.5); // how the pan is caculated
}