Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
264 views
in Technique[技术] by (71.8m points)

Use Javascript to get Maximum font size in canvas

I am drawing a canvas that needs to be on full available screen (100% width and height). I set the width and height of canvas using javascript like this

  var w = window.innerWidth;
  var h = window.innerHeight;
  var canvas = document.getElementById("myCanvas");
  canvas.width  = w;
  canvas.height = h;

After setting the canvas, I need to draw some text in it which needs to get the maximum available font size. Please help me finding the way how can I display text with maximum font size. The text may contain a single character (both upper and small case) or a string and can also contain numbers. I need to do it with javascript not jquery.

Thank you for your help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Challenge

As canvas' measureText doesn't currently support measuring height (ascent + descent) we need to do a little DOM trick to get the line-height.

As the actual height of a font - or typeface - does not necessarily (rarely) correspond with the font-size, we need a more accurate way of measuring it.

Solution

Fiddle demo

The result will be a vertical aligned text which always fit the canvas in width.

snap

This solution will automatically get the optimal size for the font.

The first function is to wrap the measureText to support height. If the new implementation of the text metrics isn't available then use DOM:

function textMetrics(ctx, txt) {

    var tm = ctx.measureText(txt),
        w = tm.width,
        h, el;  // height, div element
    
    if (typeof tm.fontBoundingBoxAscent === "undefined") {
    
        // create a div element and get height from that
        el = document.createElement('div');
        el.style.cssText = "position:fixed;font:" + ctx.font +
                           ";padding:0;margin:0;left:-9999px;top:-9999px";
        el.innerHTML = txt;

        document.body.appendChild(el); 
        h = parseInt(getComputedStyle(el).getPropertyValue('height'), 10);
        document.body.removeChild(el);

    } 
    else {
        // in the future ...
        h = tm.fontBoundingBoxAscent + tm.fontBoundingBoxDescent;
    }

    return [w, h];
}

Now we can loop to find the optimal size (here not very optimized, but works for the purpose - and I wrote this just now so there might be bugs in there, one being if text is just a single char that doesn't exceed width before height).

This function takes minimum two arguments, context and the text, the others are optional such as font name (name only), tolerance [0.0, 1.0] (default 0.02 or 2%) and style (ie. bold, italic etc.):

function getOptimalSize(ctx, txt, fontName, tolerance, tolerance, style) {

    tolerance = (tolerance === undefined) ? 0.02 : tolerance;
    fontName = (fontName === undefined) ? 'sans-serif' : fontName;
    style = (style === undefined) ? '' : style + ' ';
    
    var w = ctx.canvas.width,
        h = ctx.canvas.height,
        current = h,
        i = 0,
        max = 100,
        tm,
        wl = w - w * tolerance * 0.5,
        wu = w + w * tolerance * 0.5,
        hl = h - h * tolerance * 0.5,
        hu = h + h * tolerance * 0.5;
    
    for(; i < max; i++) {

        ctx.font = style + current + 'px ' + fontName;
        tm = textMetrics(ctx, txt);
        
        if ((tm[0] >= wl && tm[0] <= wu)) {
            return tm;
        }
        
        if (tm[1] > current) {
            current *= (1 - tolerance);
        } else {
            current *= (1 + tolerance);
        }            
    }
    return [-1, -1];
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...