苹果的MobileMe在其主页上使用JavaScript来更改电子邮件登录中的字体大小,以便用户输入时文本始终适应可用空间而不会出现溢出滚动。
虽然我知道如何在每次按键时执行函数,但我想知道如何计算每次字体大小,以便它始终适合输入字段。有没有一种方法可以测量具有可变宽度字体的文本长度?他们是如何实现这个效果的呢?
试试看,你就知道我的意思了: http://www.me.com/
苹果的MobileMe在其主页上使用JavaScript来更改电子邮件登录中的字体大小,以便用户输入时文本始终适应可用空间而不会出现溢出滚动。
虽然我知道如何在每次按键时执行函数,但我想知道如何计算每次字体大小,以便它始终适合输入字段。有没有一种方法可以测量具有可变宽度字体的文本长度?他们是如何实现这个效果的呢?
试试看,你就知道我的意思了: http://www.me.com/
过去我使用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);
})
});
});