Wer solche Diagramme mit dem Canvas Element und etwas Javascript zeichnen möchte, kann gerne diese von mir geschriebene Klasse verwenden:
function BarChartFactory(canvasElement,unitName,plotEvery){
this.canvas=canvasElement;
this.maxValue=0;
this.categoryTitleWidth=50;
this.valueTitleWidth=50;
this.bottomScalaHeight=10;
this.padding=5;
this.linesSeperateValues=true;
this.barStart=0;
this.barEnd=0;
this.barTranslationFactor=1;
this.barHeight=20;
this.barPadding=4; //top + bottom
this.xPlotEvery=plotEvery;
this.unitName=unitName;
this.categoryValueSize=2; //if more.. ignore.. if less.. paint empty
this.categories=[];
this.ctx=null;
this.width=200;
this.height=0;
this.addValue=function(categoryTitle,valueTitle,value,valueColor){
var cat=null;
for(var ii=0;ii<this.categories.length && cat==null;ii++){
if(this.categories[ii].title==categoryTitle){
cat=this.categories[ii];
console.log("found existing category: "+categoryTitle);
}
}
if(cat==null){
cat={title:"",values:[]};
cat.title=categoryTitle;
this.categories[this.categories.length]=cat;
}
cat.values[cat.values.length]={value:value,title:valueTitle,color:valueColor};
};
this.init=function(ctx,width){
this.barStart=this.categoryTitleWidth+this.valueTitleWidth;
this.barEnd=width;
for(var ii=0;ii<this.categories.length;ii++){
var cat=this.categories[ii];
for(var j=0;j<cat.values.length;j++){
if(cat.values[j].value>this.maxValue){
this.maxValue=cat.values[j].value;
}
}
if(cat.values.length>this.categoryValueSize){
this.categoryValueSize=cat.values.length;
}
}
this.maxValue=this.maxValue+(this.maxValue/10);
this.barTranslationFactor=(this.barEnd-this.barStart)/this.maxValue;
this.ctx=ctx;
this.ctx.canvas.width=width+(this.padding*2);
this.ctx.canvas.height=(this.categories.length*this.categoryValueSize*this.barHeight)+this.bottomScalaHeight+(this.padding*2);
this.width=this.ctx.canvas.width;
this.height=this.ctx.canvas.height;
//TODO clearRect
};
this.paintStructure=function(){
//paint main structure
this.ctx.strokeStyle="#AAAAAA";
this.ctx.beginPath();
this.ctx.moveTo(this.categoryTitleWidth+this.valueTitleWidth,0+this.padding);
this.ctx.lineTo(this.categoryTitleWidth+this.valueTitleWidth,this.height-this.barHeight+this.barPadding);
this.ctx.stroke();
if(this.xPlotEvery>0){
console.log("paint structure ("+this.maxValue+")");
var xStart=this.categoryTitleWidth+this.valueTitleWidth;
for(var i=this.xPlotEvery;i<this.maxValue;i=i+this.xPlotEvery){
this.ctx.beginPath();
this.ctx.moveTo(xStart+(i*this.barTranslationFactor),0+this.padding);
this.ctx.lineTo(xStart+(i*this.barTranslationFactor),this.height-this.barHeight+this.barPadding);
this.ctx.stroke();
this.ctx.fillStyle="#000000";
this.ctx.fillText(""+Math.round(i)+this.unitName,xStart+(i*this.barTranslationFactor), this.height-this.barHeight+this.barPadding+12);
}
}
};
this.paint=function(width){
this.init(this.canvas.getContext("2d"),width);
this.ctx.lineWidth=1;
this.ctx.strokeStyle="#000000";
this.paintStructure();
this.ctx.strokeStyle="#000000";
for(var iC=0;iC<this.categories.length;iC++){
var cat=this.categories[iC];
this.ctx.fillStyle="#000000";
this.ctx.fillText(cat.title,this.padding,(((iC)*this.categoryValueSize)+Math.round(this.categoryValueSize/2))*this.barHeight+this.padding);
for(var i=0;i<this.categoryValueSize;i++){
var value={value:0,title:"",color:"#FF0000"};
if(cat.values){
value=cat.values;
}
this.ctx.fillStyle="#000000";
this.ctx.fillText(value.title,this.categoryTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight);
//line under value title
this.ctx.beginPath();
if(i==this.categoryValueSize-1){
this.ctx.moveTo(this.padding,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
else{
this.ctx.moveTo(this.categoryTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
if(this.linesSeperateValues){
this.ctx.lineTo(this.width-this.padding,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
else{
this.ctx.lineTo(this.categoryTitleWidth+this.valueTitleWidth,((iC*this.categoryValueSize)+i+1)*this.barHeight+this.padding);
}
this.ctx.stroke();
//paint real value
this.ctx.beginPath();
this.ctx.rect(this.categoryTitleWidth+this.valueTitleWidth,((iC*this.categoryValueSize)+i)*this.barHeight+this.padding+this.barPadding,value.value*this.barTranslationFactor,this.barHeight-(this.barPadding*2));
this.ctx.stroke();
this.ctx.fillStyle=value.color;
this.ctx.fill();
}
}
};
}
Das Beispiel zum Bild sieht dann so aus:
<html>
<head>
<title>2dbar test</title>
<script type="text/javascript" src="./BarChartFactory.js"></script>
</head>
<body>
<canvas id="can" style="border:1px solid #000000;border-radius:4px;">
</canvas>
<script type="text/javascript">
var bcf=new BarChartFactory(document.getElementById("can"),"fps",10);
bcf.addValue("386SX","16 Mhz",20,"#70B4B6");
bcf.addValue("386SX","25 Mhz",25,"#0000FF");
bcf.addValue("386DX","25 Mhz",40,"#70B4B6");
bcf.addValue("386DX","33 Mhz",60,"#70B4B6");
bcf.paint(400);
</script>
</body>
</html>