Jeg har valgt å legge ut fargene som RGB-verdier. Jeg kunne ha valgt andre formater,
Et av mange nyttig verkøy for å se på fargeformatering er: CSS Color Converter.
Du kan kopiere denne løsningen fra denne zipfile kurver.zip Den inneholder en kjørbar versjon med data i flere formater.
Som du ser viser grafen prosentverdier. Jeg har valgt å regne om alt til prosent.
Det betyr også at hvis dataene er oppgitt som 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 dersom vi ikke har kontroll over alle utfallsmulighetene.
Hvis vi f.eks. kuttet ut Ap i dataene ovenfor ville alle de andre verdiene
fremstille "prosentfordelingen av de som har valgt et annet parti enn AP".
Jeg har valgt å betrakte koden som tre komponenter: sketch.js, datasett.js, histogram.js
sketch.js. Denne vil måtte endre seg etter hvilke data vi skal framstille, hvor mange kurver vi vil se samtidig osv.
datasett.js. Denne inneholder en objektbeskrivelse. datasett skal implementere prosentberegningen,
og den skal kunne levere data som histogram-koden spør etter.
De dataene som leveres skal også kunne støtte andre framstillingsformer,
som f.eks kurver eller kakediagram. De funksjonene som skal med er:
histogram.js. Dette er selve kurveframstillingen. Den skal arbeide på den måten at den
får et datasett å jobbe med og spør dette etter de data som trengs.
Selve hovedskissen, sketch.js, er svært enkel og må som sagt tilpasses etter behov.
_kurver.js
/*
kurver fra json-data
*/
var jsonObjekt;
var datakilde="data/valg.json";
//var datakilde="data/karakterer.json";
var DS;
function preload() {
jsonObjekt = loadJSON(datakilde);
}
function setup(){
var canvas = createCanvas(400,400);
// plasserer det
canvas.parent('canvasHere');
DS=new jsonData(jsonObjekt);
}
function draw(){
background(255);
tegnHistogram(DS,0,0,width,height);
noLoop();
}
De innleste JSON-dataene ordnes i en egen klasse, jsonData.
_jsonData.js
/*
Preparerer JSON-data for uttegning
*/
function jsonData(jsonObjekt){
//-----------------------
// setter opp data fra et JSONObject
this.tittel=jsonObjekt.tittel;
this.elementer=jsonObjekt.resultater;
this.maxVerdi=0;
this.sum=0;
// regn om til prosent. hvis det er prosent
// fra før så forblir det prosent
for(var i=0;i < this.elementer.length;i++){
this.maxVerdi=
Math.max(this.elementer[i].verdi,this.maxVerdi);
this.sum+=this.elementer[i].verdi;
// hvit hvis fargen mangler
if(!this.elementer[i].farge)
this.elementer[i].farge="255,255,255";
}
// lag prosent
for(var i=0;i < this.elementer.length;i++){
this.elementer[i].verdi=
this.elementer[i].verdi*100/this.sum;
}
this.maxVerdi=this.maxVerdi*100/this.sum;
//---------------------------------
// attributtene under må være med
// de brukes av tegnefunksjonen
this.getAntallVerdier=function(){
return this.elementer.length;
}
this.getVerdi=function(i){
return this.elementer[i].verdi;
}
this.getMaxVerdi=function(i){
return this.maxVerdi;
}
this.getNavn=function(i){
return this.elementer[i].navn;
}
this.getTittel=function(){
return this.tittel;
}
this.getFarge=function(i){
var rgb =this.elementer[i].farge.split(",");
return color(parseInt(rgb[0]),
parseInt(rgb[1]),
parseInt(rgb[2]));
}
}
Funksjonen som tegner histogrammet er plassert i en egen fil, histogram.js.
Å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. Kanskje vi kunne lagt teksten på skrå?
_histogram.js
/*
uttegning av et histogram fra datasett DS,
plassert med Top,Left,Width,Height
*/
function tegnHistogram(DS,L,T,W,H){
push();
translate(L,T);
textSize(10);
// konstanter som gir oss rammer
// for uttegningen
var marginL=30;
var marginT=50;
var marginR=10;
var marginB=30;
// ram det inn
noFill();
rect(0,0,W-1,H-1);
// noen variable for å lette resonnementet
// indre rektangel innenfor margene
var innerL=marginL;
var innerT=marginT;
var innerH=H-marginT-marginB;
var innerW=W-marginL-marginR;
var innerB=H-marginB;
// legger til 10 for å få en
// markering over største verdi
var maxVerdi=DS.getMaxVerdi()+10;
// x-aksen med søyler
line(innerL,innerB,innerL+innerW,innerB);
var antall=DS.getAntallVerdier();
var dx=innerW/antall;
for(var i=0; i< antall; i++){
var 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(parseFloat(DS.getVerdi(i)).toFixed(1),
innerL+i*dx+dx/2,innerB-yval);
}
// y-aksen
line(innerL,innerT,innerL,innerT+innerH);
// marker hver 10.
for(var i=0; i <= maxVerdi; i+=10){
var 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);
pop();
}
Oppgaverforslag
Merk at du vil ha nytte av både kode og data beskrevet på siden: Dataformater