2

In KonvaJS Text Object there is a property fontSize like fontSize: 30 but I need to stretch the text according the width and height I give for it.

Here what I wrote:

var textX = new Konva.Text({
            text: 'X',
            align: 'center',
            x: 60,
            y: 60,
            width: 60,
            height: 40
        });

What do you suggest to let the code work?

Mahdi Alkhatib
  • 1,954
  • 1
  • 29
  • 43
  • @lavrton there should be something straightforward in KonvaJS library? – Mahdi Alkhatib Aug 23 '16 at 06:54
  • 1
    The `scaledFontsize` function in my answer is only 6 simple lines long ... that's straightforward. :-) – markE Aug 24 '16 at 04:12
  • @markE creating too much canvases is not friendly with memory. – Mahdi Alkhatib Aug 24 '16 at 07:46
  • 1
    There is only 1 canvas and it's only temporarily created. The Garbage Collector will reclaim the memory very quickly. You can even run `scaledFontSize` with a zero memory footprint. Since the canvas is not used to actually draw on, you can get a reference to your Kinetic/Konva canvas and use it to `measureText`. :-) – markE Aug 24 '16 at 16:29

1 Answers1

6

Text fonts may not incrementally scale to exactly fit a desired width, but you can come close.

  • Create an in-memory canvas element,
  • Measure your text at a certain px testFontsize (almost any reasonable test size will do),
  • The needed font size is: testFontsize*desiredWidth/measuredWidth,
  • Set the needed px font size in your Konva.Text.

Notes: Some fonts do not scale with decimal precision so you might have to .toFixed(0) the resulting scaled font size. Some fonts may not incrementally scale at all and you will get the nearest available font size -- which might not fill the desired width well.

Example code:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

// define the desired text, fontsize and width
var text='Scale Me';
var fontface='verdana';
var desiredWidth=60;

$myslider=$('#myslider');
$myslider.attr({min:30,max:200}).val(desiredWidth);
$myslider.on('input change',function(){ 
    desiredWidth=parseInt($(this).val());
    ctx.clearRect(0,0,cw,ch);
    draw(text,fontface,desiredWidth) 
});

draw(text,fontface,desiredWidth);

function draw(text,fontface,desiredWidth){
    // calc the scaled fontsize needed to fill the desired width
    var scaledSize=scaledFontsize(text,fontface,desiredWidth);
    // Demo: draw the text at the scaled fontsize
    ctx.font=scaledSize+'px '+fontface;
    ctx.textAlign='left';
    ctx.textBaseline='middle';
    ctx.strokeRect(0,0,desiredWidth,100);
    ctx.fillText(text,0,50);
    ctx.font='14px verdana';
    ctx.fillText(scaledSize+'px '+fontface+' fits '+desiredWidth+'px width',10,125);
}

function scaledFontsize(text,fontface,desiredWidth){
    var c=document.createElement('canvas');
    var cctx=c.getContext('2d');
    var testFontsize=18;
    cctx.font=testFontsize+'px '+fontface;
    var textWidth=cctx.measureText(text).width;
    return((testFontsize*desiredWidth/textWidth));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Desired Width:&nbsp<input id=myslider type=range><br>
<canvas id="canvas" width=300 height=256></canvas>
markE
  • 102,905
  • 11
  • 164
  • 176