Search code examples
javascriptcanvaskineticjskonvajs

How to stretch text value in konvaJS to certain width and height?


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?


Solution

  • 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>