user2675495 user2675495 - 7 months ago 23
HTML Question

HTML canvas measureText().width is too big

I try to find out the width of a text in a html canvas.
I'm using the measureText method but it gives me a value the is more than double as expected. I generate the Text by using the toSting method. If I just hard code the return from toSting into measureText it works fine...

console.log("--->width "+this.ctx.measureText("-100").width);


returns 22

console.log(labels[i]);


returns "-100"

console.log("->width "+this.ctx.measureText(labels[i]).width);


returns 48

Any ideas why?

thanks for help!

Here is the whole code: https://jsfiddle.net/falkinator/Lze1rnm5/4/



function createGraph(){
this.canvas = document.getElementById("graph");
this.ctx = this.canvas.getContext("2d");
this.options={};
this.datasets=[];
this.options.fontSize=11;
this.ctx.font=this.options.fontSize+"px Arial";
this.ctx.textAlign="left";
this.ctx.textBaseline="middle";
this.datasetLength=500;
this.dataset=function(options){
/*this.strokeColor=options.strokeColor;
this.signalName=options.signalName;
this.signalMin=options.signalMin;
this.signalMax=options.signalMax;
this.signalUnit=options.signalUnit;*/
this.data=[];
this.min;
this.max;
};
this.buildYLabels = function(scaleMin, scaleMax){
var labels = [];
var maxLabelWidth=0;
console.log("--->width "+this.ctx.measureText("-100").width);
for(i=10;i>=0;i--){
labels.push((scaleMin+((scaleMax-scaleMin)/10)*i).toString());
console.log((scaleMin+((scaleMax-scaleMin)/10)*i).toString());
console.log("->width "+this.ctx.measureText(labels[i]).width);
if(maxLabelWidth<this.ctx.measureText(labels[i]).width){
maxLabelWidth=this.ctx.measureText(labels[i]).width;
}
}
return {labels: labels,
maxLabelWidth: maxLabelWidth};
};
this.buildXLabels = function(x){

};
this.draw = function (){
var _this=this;
each(this.datasets,function(dataset, index){
//plot data
if(index>0)return;
//draw scale
var canvasHeight = _this.canvas.height;
console.log("canvas height="+canvasHeight);
var yLabels = _this.buildYLabels(-100, 500);
var currX = _this.options.fontSize/2;
var scaleHeight = canvasHeight-_this.options.fontSize*1.5;
var maxLabelWidth=yLabels.maxLabelWidth;
console.log(yLabels.maxLabelWidth);
each(yLabels.labels,function(label, index){
_this.ctx.fillText(label,0,currX);
console.log(label);
currX+=(scaleHeight/10);
});
_this.ctx.beginPath();
_this.ctx.moveTo(maxLabelWidth,0);
_this.ctx.lineTo(maxLabelWidth,canvasHeight);
_this.ctx.stroke();
});
};
this.addSignal = function(){
var dataset = new this.dataset({});
this.datasets.push(dataset);
};
this.pushData = function(data){
var _this=this;
if(data.length!=this.datasets.length){
console.error("the number of pushed data is diffrent to the number of datasets!");
return;
}
each(data,function(data, index){
_this.datasets[index].data.push(data);
if(_this.datasets[index].data.length>_this.datasetLength){
_this.datasets[index].data.shift();
}
});
};
this.calculateScaling = function(dataset){
var range = dataset.max - dataset.min;
var decStep = Math.pow(10,Math.floor(Math.log10(range)));
var scaleMin = roundTo(dataset.min/*+(decStep*10)/2*/, decStep);
var scaleMax = roundTo(dataset.max/*+(decStep*10)/2*/, decStep);
var scaleStep = (scaleMax - scaleMin)/10;
};
var minx=-34, maxx=424;
var range = maxx - minx;
var decStep = Math.pow(10, Math.floor(Math.log10(range)));
var scaleMin = roundTo(minx-(decStep/2), decStep);
var scaleMax = roundTo(maxx+(decStep/2), decStep);
var scaleStep = (scaleMax - scaleMin)/10;
console.log(this.buildYLabels(scaleMin,scaleMax));
console.log("range="+range);
console.log("log="+Math.floor(Math.log10(range)));
console.log("scaleStep="+scaleStep);
console.log("decStep="+decStep);
console.log("scaleMin="+scaleMin);
console.log("scaleMax="+scaleMax);
}
graph = new createGraph();
graph.addSignal();
graph.addSignal();
graph.addSignal();

graph.pushData([1,2,3]);
graph.pushData([1,2,3]);
graph.draw();
function each(array, callback){
console.log(callback);
for(i in array){
callback(array[i], i);
}
}
function roundTo(num, to){
return Math.round(num/to)*to;
}

<canvas id="graph"></canvas>




Answer

In your code that generates the labels, the loop index i is going from 10 to 0. Each time though the loop you are pushing a new label to the array (i.e. labels[0], labels[1], ...) but you are attempting to measure the labels using the loop index i (i.e. labels[10], labels[9], ...). Thus, the first few measurments are of the text "undefined".

Change...

console.log("->width "+this.ctx.measureText(labels[i]).width);
if(maxLabelWidth<this.ctx.measureText(labels[i]).width){
    maxLabelWidth=this.ctx.measureText(labels[i]).width;

to...

console.log("->width "+this.ctx.measureText(labels[labels.length-1]).width);
if(maxLabelWidth<this.ctx.measureText(labels[labels.length-1]).width){
    maxLabelWidth=this.ctx.measureText(labels[labels.length-1]).width;