使用Javascript在用户输入时缩小字体大小以适应输入框。

10

苹果的MobileMe在其主页上使用JavaScript来更改电子邮件登录中的字体大小,以便用户输入时文本始终适应可用空间而不会出现溢出滚动。

虽然我知道如何在每次按键时执行函数,但我想知道如何计算每次字体大小,以便它始终适合输入字段。有没有一种方法可以测量具有可变宽度字体的文本长度?他们是如何实现这个效果的呢?

试试看,你就知道我的意思了: http://www.me.com/


请参见https://dev59.com/tHI-5IYBdhLWcg3w-9wK。 - philfreo
2个回答

28

过去我使用jQuery做过这件事。您可以像这样测量文本的大小:

// txt is the text to measure, font is the full CSS font declaration,
// e.g. "bold 12px Verdana"
function measureText(txt, font) {
    var id = 'text-width-tester',
        $tag = $('#' + id);
    if (!$tag.length) {
        $tag = $('<span id="' + id + '" style="display:none;font:' + font + ';">' + txt + '</span>');
        $('body').append($tag);
    } else {
        $tag.css({font:font}).html(txt);
    }
    return {
        width: $tag.width(),
        height: $tag.height()
    }
}

var size = measureText("spam", "bold 12px Verdana");
console.log(size.width + ' x ' + size.height); // 35 x 12.6
为了将其适应给定的空间,这有点棘手-您需要分离font-size声明并适当缩放。根据您的操作方式,如果您拆分font声明的不同部分,则可能最容易。调整大小函数可能如下所示(再次强调,这显然依赖于jQuery):
function shrinkToFill(input, fontSize, fontWeight, fontFamily) {
    var $input = $(input),
        txt = $input.val(),
        maxWidth = $input.width() + 5, // add some padding
        font = fontWeight + " " + fontSize + "px " + fontFamily;
    // see how big the text is at the default size
    var textWidth = measureText(txt, font).width;
    if (textWidth > maxWidth) {
        // if it's too big, calculate a new font size
        // the extra .9 here makes up for some over-measures
        fontSize = fontSize * maxWidth / textWidth * .9;
        font = fontWeight + " " + fontSize + "px " + fontFamily;
        // and set the style on the input
        $input.css({font:font});
    } else {
        // in case the font size has been set small and 
        // the text was then deleted
        $input.css({font:font});
}

这个示例可以在这里查看:http://jsfiddle.net/nrabinowitz/9BFQ8/5/

测试表明,至少在Google Chrome中会有一些不稳定,因为只使用了全整数字号。您可能可以通过基于em的字体声明来实现更好的效果,尽管这可能有点棘手 - 您需要确保文本宽度测试器的 1em 大小与输入框的大小相同。


真的吗?对于一个完全功能且相对清晰的与你感兴趣的确切事物相关的示例,一点爱都没有吗? - nrabinowitz
不,完全不是那样的。谢谢,非常完美。我陷入了法律问题(公司注册、商标、服务条款和隐私政策),两天没能登录SO。很抱歉回复晚了以及延迟点赞和标记为已回答。 - Andrew De Andrade
谢谢!如果我有点任性,对不起 - 我很感激您的考虑。 - nrabinowitz
谢谢你帮我做这个,效果非常好。没问题,不用客气。 - Andrew De Andrade
大家好,我使用了这个例子并将其翻译成了React。如果你想看一下,可以访问https://codepen.io/sanchitos/pen/yLXGZrg。 - Sanchitos
显示剩余2条评论

2

我从其他答案中混合了一些内容制作了另一个答案。我认为这提供了最简单的一种属性更改解决方案。

可能会有点啰嗦或需要以某种方式进行重构以提高清晰度,欢迎任何建议!

$(document).ready(function(){

    // get the current styles size, in px integer.
    var maxSize = parseInt($('.fields').css("font-size"));

    function isOverflowed (element){

        if ( $(element)[0].scrollWidth > $(element).innerWidth() ) {
            return true;
        } else {
            return false;
        }
    };

    function decreaseSize (element){

        var fontSize = parseInt($(element).css("font-size"));
        fontSize = fontSize - 1 + "px";
        $(element).css({'font-size':fontSize});

    }

    function maximizeSize (element){

        var fontSize = parseInt($(element).css("font-size"));
        while (!isOverflowed(element) && fontSize < maxSize){
            fontSize = fontSize + 1 + "px";
            $(element).css({'font-size':fontSize});

            // if this loop increases beyond the width, decrease again. 
            // hacky.
            if (isOverflowed(element)){
                while (isOverflowed(element)) {
                    decreaseSize(element);
                }            
            }     

        }        

    }

    function fixSize (element){
        if (isOverflowed(element)){
            while (isOverflowed(element)) {
                decreaseSize(element);
            }            
        } else {
            maximizeSize(element);
        }
    }

    // execute it onready.
    $('.fields').each(function(){
        fixSize(this);
    });

    // bind to it.
    $(function() {
        $('.fields').keyup(function() {
            fixSize(this);
        })
    });    

});

1
这看起来/感觉像是一个更优雅的解决方案。我在这里创建了一个JSFiddle:https://jsfiddle.net/dsuv8onp/ - Wouter
另外,如果您想将其默认应用于所有文本字段,则可以使用 $('input [type = text]')而不是.fields。 - Wouter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接