1

I have an algorithm for reducing a font size in a given text box if the text is too big for the box (fit to box)

and it works just fine, but it's really inefficient as it's literally just reducing the font size by 1 till it fits.

Can anyone help me make it more efficient, such as binary chopping or something?

the code is:

function fitToBox(object, maxFontSize, minFontSize, maxHeight) {
    var box = document.getElementById(object);
    var currentHeight = box.offsetHeight;                       
    var currentFontSize = maxFontSize;                  
    do {
        box.style.fontSize = currentFontSize+"pt";
        currentFontSize = box.style.fontSize.replace("pt", "");
        currentHeight = box.offsetHeight;                                                       
        if(currentHeight >= maxHeight) {
            currentFontSize -= 1;
        }
    } while (currentHeight > maxHeight && currentFontSize > minFontSize);
    box.style.lineHeight = currentFontSize+"pt";
}

Complete example in HTML (just add more text to the div to see the fitting in progress)

<html>
<head>
<script type="text/javascript">
function fitToBox(object, maxFontSize, minFontSize, maxHeight) {
    var box = document.getElementById(object);
    var currentHeight = box.offsetHeight;                       
    var currentFontSize = maxFontSize;                  
    do {
        box.style.fontSize = currentFontSize+"pt";
        currentFontSize = box.style.fontSize.replace("pt", "");
        currentHeight = box.offsetHeight;                                                       
        if(currentHeight >= maxHeight) {
            currentFontSize -= 1;
        }
    } while (currentHeight > maxHeight && currentFontSize > minFontSize);
    box.style.lineHeight = currentFontSize+"pt";
}
</script>
</head>
<body>

<div id="fitme" style="background-color: yellow; font-size: 24pt; width: 400px;">
    This is some text that is fit into the box This is some text that is fit into the box This is some text that is fit into the box
</div>

<script type="text/javascript">
    fitToBox("fitme", 24, 4, 80);
</script>

</body>
</html>
4

3 に答える 3

1

Here's a version which reduces the loop count from 9 in your example to 4:

function fitToBox(box, maxFontSize, minFontSize, maxHeight) {
    inc = (maxFontSize - minFontSize) / 2;
    currentFontSize = minFontSize + inc;
    box.style.fontSize = currentFontSize+"pt";
    while(inc >= 1) {
        if(box.offsetHeight > maxHeight) {
            dir = -1;
        } else {
            dir = 1;
        }
        inc = Math.floor(inc/2);
        currentFontSize += (dir * inc);
        box.style.fontSize = currentFontSize+"pt";
    }
}

It starts by assuming the midway size is a good start and binary chops its way to the best fit below the maximum, changing direction as required.

I can't work out why you're changing the CSS line-height so I haven't done that.

于 2012-11-29T22:42:20.687 に答える
0

Could you do something like this where you measure the font height in px?

 function fitToBox(object, maxFontSize, minFontSize, maxHeight) {
     var box = document.getElementById(object);                       
     var currentFontSize = box.offsetHeight - 6; //however much space you want to leave                  
     if(currentFontSize > maxFontSize){
          currentFontSize = maxFontSize;
     }else if(currentFontSize < minFontSize){
          currentFontSize = minFontSize;
     }
     box.style.lineHeight = currentFontSize+"px";
  }
于 2012-11-28T16:43:39.717 に答える
0

Try counting the max allowed size based on the box styling.

Get the elements height - top padding - bottom padding and you'll get your max size.

var height = parseInt(box.clientHeight);
var pt = parseInt(box.style.paddingTop);
var pb = parseInt(box.style.paddingBottom);
var fontsize = (height - pt - pb) + "px";

As for the next part. Solution that comes to mind when it comes to detecting overflow is to do something like.

var boxClone = box.cloneNode(true)
boxClone.style.visibility = "hidden";
boxClone.id = "boxClone";
document.getElementsByTagName('body')[0].appendChild(boxClone);

box.onkeydown = function(e) { 

}

In the keydown event, intercept the char thats about to get appended and append it into the boxclone - then measure its size and compare it to the original. Once you know the numbers you can adjust your text accordingly.

于 2012-11-28T16:45:42.383 に答える