HTML
>
Canvas
>
Processing
>Befolkning
Visualisering av data
Folkemengde i Norge
Fordelt på alder [0:105+] i perioden 1986 - 2013 Kvinner og menn
Hvor er du ?
Det er tre involverte processing-filer:
_folkiNorge.pde
/*
Data from Statistisk Sentralbyrå(SSB):
http://data.ssb.no/api/v0/dataset/1082?lang=no
http://data.ssb.no/api/v0/dataset/1082.csv?lang=no
CSV data is cleaned and compressed to files:
men.csv, women.csv og all.csv
included years [1986,2013]
The clean and compress-job is done by the author in project
web\commondata\\SSB
(just so I remember)
BS Juni 2013
*/
int STARTYEAR=1986;
int currentYear;
// the year we want to hilite
int myYear=1990;
// want one for each year
CurveYear[] curves;
PFont bigFont;
PFont smallFont;
void setup(){
size(600,600);
// from the net or a local copy
// alternativ addresses:
// "http://www.it.hiof.no/~borres/commondata/SSB/befolkning/data/all.csv");
int currentYear=0;
// give each year three datasett
setUpDataSet("data/all.csv","data/men.csv","data/women.csv");
// set equal max value on all curves
float totalMaxValue=curves[0].maxValue;
for(int i=0;i< curves.length;i++){
if(curves[i].maxValue > totalMaxValue)
totalMaxValue=curves[i].maxValue;
}
for(int i=0;i< curves.length;i++){
curves[i].maxValue=totalMaxValue;
}
bigFont=createFont("Arial", 18);
smallFont=createFont("Arial", 12);
frameRate(20);
}
void draw(){
background(255);
// you may provide a birth year so you can identify yourself on the curve
// a number off scale will not be shown ( i.e 2020)
curves[currentYear].draw(myYear);
}
void setUpDataSet(String filenameAll,String filenameMen,String filenameWomen){
// read the complete file as lines
String linesAll[] = loadStrings(filenameAll);
String linesMen[] = loadStrings(filenameMen);
String linesWomen[] = loadStrings(filenameWomen);
// make a Kurve for each line
// assuming data is correct
curves=new CurveYear[linesAll.length];
for(int i=0;i<curves.length;i++){
curves[i]=new CurveYear(new DataSet(linesAll[i],color(0)),
new DataSet(linesMen[i],color(0,0,255)),
new DataSet(linesWomen[i],color(255,0,0)),
STARTYEAR+i);
}
}
// step to next year
void mousePressed(){
setNextYear();
}
//----------------------------
// communicate with webpage
int getFirstYear(){
return STARTYEAR;
}
int getLastYear(){
return curves.length-STARTYEAR;
}
// set next year
void setNextYear(){
currentYear++;
if(currentYear >= curves.length)
currentYear=0;
}
// set previous year
void setPreviousYear(){
currentYear--;
if(currentYear < 0)
currentYear=0;
}
void setMyYear(int y){
myYear=y;
}
og
_CurveYear.pde
/*
Will handle one year, with three dataset
allpersons, men and women
Could be generalized to an ArrayList of dataset
This version knows the curved, an
*/
class CurveYear{
DataSet allPersons;
DataSet men;
DataSet women;
int year;
// when we draw
float maxValue;
float minValue;
float sum;
final float MARGIN=40;
float curveWidth=width-2*MARGIN;
float curveHeight=height-2*MARGIN;
float noOfValues;
CurveYear(DataSet allPersons,DataSet men,DataSet women,int year){
this.allPersons=allPersons;
this.men=men;
this.women=women;
this.year=year;
// find max, min, sum
maxValue=allPersons.getMaxValue();
minValue=allPersons.getMinValue();
noOfValues=allPersons.getNoOfValues();
sum=allPersons.getSum();
}
void draw(int markedBirthYear){
// markedBirthYear is a a year where someone is born
// we can "see" this person on the curve.
//---------------------
//Y axis
stroke(0);
line(MARGIN,MARGIN,MARGIN,MARGIN+curveWidth);
// mark each 100000 value
stroke(200);
textFont(smallFont);
float v=10000;
while(v< maxValue){
float mark=map(v,minValue,maxValue,MARGIN+curveHeight,MARGIN);
line(MARGIN, mark,MARGIN+curveWidth,mark);
text(int(v),0,mark);
v=v+10000;
}
//---------------------------
//x-axis
stroke(0);
line(MARGIN,height-MARGIN,width-MARGIN,height-MARGIN);
//mark each tenth age
stroke(200);
textFont(smallFont);
int age=10;
while(age < noOfValues){
float ageMark=map(age,0,noOfValues,MARGIN,MARGIN+curveWidth);
line(ageMark,MARGIN,ageMark,MARGIN+curveWidth);
text(age,ageMark-10,MARGIN+curveHeight+20);
age+=10;
}
// mark follow year
age=year-markedBirthYear;
if(age < 105 && age > 0){
stroke(0,255,0);
float ageMark=map(age,0,noOfValues,MARGIN,MARGIN+curveWidth);
line(ageMark,MARGIN,ageMark,MARGIN+curveWidth);
}
//------------------
// curves
// parameters scale the curve
allPersons.draw(minValue,maxValue, MARGIN,MARGIN,curveWidth,curveHeight);
men.draw(minValue,maxValue,MARGIN,MARGIN,curveWidth,curveHeight);
women.draw(minValue,maxValue,MARGIN,MARGIN,curveWidth,curveHeight);
//-------------
//year and sum
fill(0);
textFont(bigFont);
text(year,width-MARGIN-textWidth(str(int(sum))),MARGIN);
text(int(sum),width-MARGIN-textWidth(str(int(sum))),MARGIN+30);
}
}
og
_DataSet.pde
/*
describes data for one year. That is one value for each
of [1986..2013]
*/
class DataSet{
float maxValue;
float minValue;
float sum;
float[] values; // all values
color displayColor;
DataSet(String csvline, color displayColor){
this.displayColor=displayColor;
// pick each comma separated value on the line
String[] parts=csvline.split(",");
values=new float[parts.length];
// init max,min,sum
values[0]=float(parts[0]);
maxValue=values[0];
minValue=0;
sum=values[0];
// set the rest of values and update min,max,sum
for(int i=1;i< parts.length;i++){
values[i]=float(parts[i]);
if(values[i] > maxValue)
maxValue=values[i];
sum=sum+values[i];
}
}
// scaling parameters
void draw(float minValue,float maxValue,float cLeft, float cTop, float cWidth,float cHeight){
stroke(displayColor);
for(int i=0;i<values.length-1;i++){
float x1=map(i,0,values.length,cLeft,cLeft+cWidth);
float x2=map(i+1,0,values.length,cLeft,cLeft+cWidth);
float y1=map(values[i],minValue,maxValue,cTop+cHeight,cTop);
float y2=map(values[i+1],minValue,maxValue,cTop+cHeight,cTop);
line(x1,y1,x2,y2);
}
}
float getMaxValue(){
return maxValue;
}
float getMinValue(){
return minValue;
}
float getSum(){
return sum;
}
int getNoOfValues(){
return values.length;
}
}
Javascriptkoden er slik, med to funksjoner som kaller skissen:
_index.js
function showNextYear(){
// identify processing
var pjs=Processing.getInstanceById("draw1");
pjs.setNextYear()
}
function showPreviousYear(){
// identify processing
var pjs=Processing.getInstanceById("draw1");
pjs.setPreviousYear()
}
function setMyYear(){
// identify processing
var pjs=Processing.getInstanceById("draw1");
var y=document.getElementById("year").value;
if(/^[0-9]{4}$/.test(y))
pjs.setMyYear(y);
else
alert ("4 siffere");
}