Уменьшение размера шрифта для пользовательских типов, чтобы соответствовать вводу с использованием Javascript
Apple MobileMe использует javascript для изменения размера шрифта при входе в электронную почту на своей домашней странице, когда пользователь вводит текст, чтобы текст всегда помещался в доступное пространство без прокрутки переполнения.
Хотя я вижу, как выполнять функцию при каждом нажатии клавиши, мне любопытно, как каждый раз рассчитывать размер шрифта, чтобы он всегда вписывался в поле ввода. Есть ли способ измерить длину фрагмента текста шрифтом переменной ширины? Как они достигают этого эффекта?
Попробуйте, чтобы понять, что я имею в виду: http://www.me.com/
2 ответа
Я делал это в прошлом, используя 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
Размер тестера ширины текста такой же, как и для ввода.
Я сделал еще один из мешанины других ответов. Я думаю, что это обеспечивает самое простое решение с одним изменением свойства.
Это, вероятно, слишком многословно или может быть реорганизовано для ясности, любые предложения приветствуются!
$(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);
})
});
});