![Børre Stenseth](http://www.it.hiof.no/~borres/allround/selfimages/bs.gif)
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"); }