Уменьшение размера шрифта для пользовательских типов, чтобы соответствовать вводу с использованием Javascript - PullRequest
9 голосов
/ 24 мая 2011

Apple MobileMe использует javascript для изменения размера шрифта в имени пользователя электронной почты на своей домашней странице, когда пользователь вводит текст, чтобы текст всегда помещался в доступное пространство без прокрутки переполнения.

Хотя я могу видеть, как выполнять функцию при каждом нажатии клавиши, мне любопытно, как можно рассчитывать размер шрифта каждый раз, чтобы он всегда вписывался в поле ввода. Есть ли способ измерить длину фрагмента текста шрифтом переменной ширины? Как они достигают этого эффекта?

Попробуйте, чтобы понять, что я имею в виду: http://www.me.com/

Ответы [ 2 ]

27 голосов
/ 24 мая 2011

Я делал это в прошлом, используя 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 для тестера ширины текста такой же, как и для ввода .

0 голосов
/ 01 февраля 2016

Я сделал еще один из множества других ответов. Я думаю, что это обеспечивает самое простое решение с одним изменением свойства.

Вероятно, он слишком многословен или может быть реорганизован для ясности, приветствуются любые предложения!

$(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);
        })
    });    

});
...