Det vi lager blir f.eks. slik
Denne framstillingen er basert på følgende JSON-fil:
{"tittel":"Stortingsvalg 2017","elementer":[
{"navn":"AP", "verdi":27.4, "farge":"240,60,54"},
{"navn":"H", "verdi":25.0, "farge":"106,155,198"},
{"navn":"Frp", "verdi":15.2, "farge":"95,65,121"},
{"navn":"SP", "verdi":10.3, "farge":"0,119,68"},
{"navn":"SV", "verdi":6.0, "farge":"222,104,47"},
{"navn":"V", "verdi":4.4, "farge":"131,189,66"},
{"navn":"Krf", "verdi":4.2, "farge":"255,190,46"},
{"navn":"MDG", "verdi":3.2, "farge":"0,167,120"},
{"navn":"R", "verdi":2.4, "farge":"164,31,45"},
{"navn":"Andre", "verdi":1.9, "farge":"102,102,102"}
]
}
Jeg har valgt å legge ut fargene som RGB-verdier. Jeg kunne ha valgt andre formater.
Et nyttig verkøy for å se på fargeformatering er: color converter
CSS Color Converter.
Som du ser viser grafen prosentverdier. Jeg har valgt å regne om alt til prosent.
Det betyr også at hvis dataene er oppgitt prosentverdier vil de forhåpentligvis fortsette å være det på grafen,
etter konverteringen (!).
Det er viktig å merke seg at denne løsningen er meningsløs derom vi ikke har kontroll over alle utfallsmulighetene.
Hvis vi f.eks. kuttet ut Ap i dataene ovenfor ville alle de andre verdiene fremstille
"prosent fordelingen av de som har valgt et annet parti enn AP".
Koden består av tre filer: kurver.pde, datasett.pde, histogram.pde
Selve hovedskissen, kurver.pde, er svært enkel og kan lett utvides til f.eks. å tegne flere grafer.
/*
Framstilling av histogram
fra JSON-data
*/
JSONObject jObj;
String datakilde="data/valg.json";
//String datakilde="data/karakterer.json";
datasett DS;
void setup(){
size(500, 500);
jObj = loadJSONObject(datakilde);
DS=new datasett(jObj);
}
void draw(){
background(255);
tegnHistogram(DS,0,0,width,height);
noLoop();
}
De innleste JSON-dataene ornes i en egen klasse, datasett. Dette er gjort for å forenkle koden og for å lage en klasse som lett kan modifiseres for å støtte andre typer uttegninger.
Det er dessuten ganske behagelig å ha en slik klasse når løsningen skal testes og modifiseres
/*
Ordner jasondata i prosentverdier
*/
class datasett{
String tittel;
JSONArray elementer;
float maxVerdi;
float sum;
datasett(JSONObject jObj){
elementer=jObj.getJSONArray("elementer");
this.tittel=jObj.getString("tittel");
maxVerdi=0;
sum=0;
// regn om til prosent
for(int i=0; i< elementer.size();i++){
float v=elementer.getJSONObject(i).getFloat("verdi");
if(v > maxVerdi)
maxVerdi=v;
sum+=v;
}
for(int i=0; i< elementer.size();i++){
float v=elementer.getJSONObject(i).getFloat("verdi");
elementer.getJSONObject(i).setFloat("verdi",v*100.0/sum);
}
maxVerdi=maxVerdi*100.0/sum;
}
//---------------------------------
// antall verdier
int getAntallVerdier(){
return elementer.size();
}
//--------------------------------
// verdier er nå prosentverdier
float getVerdi(int i){
return elementer.getJSONObject(i).getFloat("verdi");
}
float getMaxVerdi(){
return maxVerdi;
}
String getNavn(int i){
return elementer.getJSONObject(i).getString("navn");
}
String getTittel(){
return tittel;
}
color getFarge(int i){
String[] rgb=
elementer.getJSONObject(i).getString("farge").split(",");
return color(parseInt(rgb[0]),
parseInt(rgb[1]),
parseInt(rgb[2]));
}
}
Funksjonen som tegner histogrammet er plassert i en egen fil, histogram.pde. Årsaken er igjen et ønske om å skille funksjonalitet og holde orden. Det er mange ting som kan endres her.
Det er f.eks. et svakt punkt at for lange navn på x-aksen vil skape vansker. Se om du kan fikse det.
/*
Uttegning av et histogram fra datasett DS,
plassert med Top,Left,Width,Height
*/
void tegnHistogram(datasett DS,
float L,float T,float W,float H){
pushMatrix();
pushStyle();
textSize(10);
// konstanter som gir oss rammer for tegningen
int marginL=30;
int marginT=50;
int marginR=10;
int marginB=30;
translate(L,T);
// ram det inn
rect(0,0,W-1,H-1);
// noen variable for å lette resonnementet
// indre rektangel innenfor margene
float innerL=marginL;
float innerT=marginT;
float innerH=H-marginT-marginB;
float innerW=W-marginL-marginR;
float innerB=H-marginB;
// legger til 10 for å få en
// markering over største verdi
float maxVerdi=DS.getMaxVerdi()+10;
// x-aksen med søyler
line(innerL,innerB,innerL+innerW,innerB);
int antall=DS.getAntallVerdier();
float dx=innerW/antall;
for(int i=0; i< antall; i++){
float yval=map(DS.getVerdi(i),0,maxVerdi,0,innerH);
fill(DS.getFarge(i));
rect(innerL+i*dx+1,innerB-1,dx,-yval);
// under søylen og aksen
textAlign(CENTER,TOP);
fill(0);
text(DS.getNavn(i),innerL+i*dx+dx/2,innerB+10);
// over søylen
textAlign(CENTER,BOTTOM);
fill(0);
// formaterer med en desimal
text(String.format("%.1f", DS.getVerdi(i)),
innerL+i*dx+dx/2,innerB-yval);
}
// y-aksen
line(innerL,innerT,innerL,innerT+innerH);
// marker hver 10.
for(int i=0; i <= maxVerdi; i+=10){
float yval=map(i,0,maxVerdi,0,innerH);
stroke(200);
line(innerL,innerB-yval,innerL+innerW,innerB-yval);
textAlign(RIGHT,CENTER);
fill(0);
text(""+i,innerL-2,innerB-yval);
}
// tittel
textAlign(CENTER,TOP);
textSize(15);
fill(0);
text(DS.getTittel(),W/2,5);
popStyle();
popMatrix();
}
Når vi arbeider med JSON er det erfaringsmessig veldig nyttig å teste data, for å se om de er riktig formatert.
Det blir fort mange parenteser av ulik type. Det finne flere stder på nettet der du kan teste JSON-formatering.
Jeg har hatt nytte av denne : Json-parser online .
Det er også slikat de siste versjonene av nettlesere parser json og melder om feil.