[英]JavaScript Scale Text to Fit in Fixed Div
在 JavaScript/jQuery 中,如何在固定宽度的 Div 中缩放可变长度的文本行,以便一行始终适合 Div(作为一行)?
这有点像黑客,但会做你想做的。
<div id="hidden-resizer" style="visibility: hidden"></div>
将它放在页面底部,它不会移动页面上的其他元素。
然后这样做:
var size;
var desired_width = 50;
var resizer = $("#hidden-resizer");
resizer.html("This is the text I want to resize.");
while(resizer.width() > desired_width) {
size = parseInt(resizer.css("font-size"), 10);
resizer.css("font-size", size - 1);
}
$("#target-location").css("font-size", size).html(resizer.html());
HTML:
<div class="box" style="width:700px">This is a sentence</div>
<div class="box" style="width:600px">This is a sentence</div>
<div class="box" style="width:500px">This is a sentence</div>
<div class="box" style="width:400px">This is a sentence</div>
JavaScript:
$( '.box' ).each(function ( i, box ) {
var width = $( box ).width(),
html = '<span style="white-space:nowrap"></span>',
line = $( box ).wrapInner( html ).children()[ 0 ],
n = 100;
$( box ).css( 'font-size', n );
while ( $( line ).width() > width ) {
$( box ).css( 'font-size', --n );
}
$( box ).text( $( line ).text() );
});
现场演示: http : //jsfiddle.net/e8B9j/2/show/
从 URL 中删除“/show/”以查看代码。
我写了一个 jQuery 插件来做到这一点:
http://michikono.github.com/boxfit
该插件会将文本水平和垂直缩放到框内的最大可用大小,然后将其居中。
您唯一需要做的就是定义一个包含文本的 div:
<div id="scale">some text</div>
然后调用:
$('#scale').boxfit()
该方法将接受一些参数来禁用/启用文本换行和居中对齐。
对于新的浏览器,您可以使用 Inline-SVG。 这可以通过 CSS 像图像一样缩放 ..!
.smallerVersion{ max-width: 50% }
<!DOCTYPE html> <html> <head> <title>Scale SVG example</title> </head> <body> <h2>Default version:</h2> <svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg"> <style> .small { font: italic 13px sans-serif; } .heavy { font: bold 30px sans-serif; } /* Note that the color of the text is set with the * * fill property, the color property is for HTML only */ .Rrrrr { font: italic 40px serif; fill: red; } </style> <text x="20" y="35" class="small">My</text> <text x="40" y="35" class="heavy">cat</text> <text x="55" y="55" class="small">is</text> <text x="65" y="55" class="Rrrrr">Grumpy!</text> </svg> <h2>Scaled version:</h2> <svg class="smallerVersion" viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg"> <style> .small { font: italic 13px sans-serif; } .heavy { font: bold 30px sans-serif; } /* Note that the color of the text is set with the * * fill property, the color property is for HTML only */ .Rrrrr { font: italic 40px serif; fill: red; } </style> <text x="20" y="35" class="small">My</text> <text x="40" y="35" class="heavy">cat</text> <text x="55" y="55" class="small">is</text> <text x="65" y="55" class="Rrrrr">Grumpy!</text> </svg> </body> </html>
( width: 100%;
)
大多数其他答案使用循环来减小字体大小,直到它适合 div,这非常慢,因为每次字体更改大小时页面都需要重新渲染元素。 我最终不得不编写自己的算法,使其以一种允许我定期更新其内容的方式执行,而不会冻结用户浏览器。 我添加了一些其他功能(旋转文本、添加填充)并将其打包为 jQuery 插件,您可以在以下位置获取它:
https://github.com/DanielHoffmann/jquery-bigtext
简单地打电话
$("#text").bigText();
它将非常适合您的容器。
在这里查看它的实际效果:
http://danielhoffmann.github.io/jquery-bigtext/
现在它有一些限制,div 必须有固定的高度和宽度,它不支持将文本换行成多行。
Edit2:我现在已经解决了这些问题和限制,并添加了更多选项。 您可以设置最大字体大小,也可以选择使用宽度、高度或两者(默认为两者)来限制字体大小。 我将努力接受包装元素中的 max-width 和 max-height 值。
我不知道确切的方法,但这是一个近似值:
var factor = 1/3; // approximate width-to-height ratio
var div = $('#mydiv');
div.css('font-size', div.width() / (div.text().length * factor) + 'px');
您需要根据您使用的字体调整factor
。 1/3 似乎适用于 Times New Roman。
在目标类的支持下修改了@sworoc 的版本
function resizeText(text, size, target) {
var fontSize = 0;
var resizer = $('<span>');
resizer.html(text).hide();
resizer.attr('class', target.attr('class'));
$('body').append(resizer);
while(resizer.width() < size) {
fontSize++
resizer.css("font-size", fontSize);
}
target.css('font-size', fontSize).html(text);
resizer.remove();
}
resizeText("@arunoda", 350, $('#username'));
在您的 div 中,将文本放在没有填充的跨度中。 那么跨度的宽度将是文本的长度。
用于查找要使用的正确字体大小的未经测试的代码:
var objSpan = $('.spanThatHoldsText');
var intDivWidth = $('.divThatHasAFixedWidth').width();
var intResultSize;
for (var intFontSize = 1; intFontSize < 100; intFontSize++)
objSpan.css('font-size', intFontSize);
if (objSpan.width() > intDivWidth) {
intResultSize = intFontSize - 1;
break;
}
}
objSpan.css('font-size', intResultSize);
这是我想出的一个咖啡脚本解决方案。 我克隆需要调整其字体大小的元素,然后在计算结束时将其删除。 为了提高性能,我有一些代码仅在调整大小停止 200 毫秒后才执行计算。
使用类autofont标记元素,以便不显眼地完成。
#
# Automagically resize fonts to fit the width of the
# container they are in as much as possible.
#
fixfonts = ->
scaler = 1.2
for element in $('.autofont')
size = 1
element = $(element)
desired_width = $(element).width()
resizer = $(element.clone())
resizer.css
'font-size': "#{size}em"
'max-width': desired_width
'display': 'inline'
'width': 'auto'
resizer.insertAfter(element)
while resizer.width() < desired_width
size = size * scaler
resizer.css
'font-size': "#{size}em"
$(element).css
'font-size': "#{size / scaler }em"
resizer.remove()
$(document).ready =>
fixfonts()
timeout = 0
doresize = ->
timeout--
if timeout == 0
fixfonts()
$(window).resize ->
timeout++
window.setTimeout doresize, 200
我有一个类似的问题,这让我为此编写了自己的插件。 一种解决方案是使用收缩贴合方法,如上所述。 但是,如果您必须适应多个项目或关心性能,例如调整窗口大小,请查看jquery-quickfit 。
它测量并计算适合文本的每个字母的大小不变度量,并使用它来计算适合文本到容器中的下一个最佳字体大小。
计算被缓存,这使得它在处理多个文本或必须多次适应文本时非常快(从第二次调整大小开始实际上没有性能影响),例如在窗口调整大小时。
这是我对@teambob 的建议(在上面的评论中)的修改,它也考虑了容器的高度:
<div class="box" style="width:700px; height:200px">This is a sentence</div>
<div class="box" style="width:600px; height:100px">This is a sentence</div>
<div class="box" style="width:500px; height:50px">This is a sentence</div>
<div class="box" style="width:400px; height:20px">This is a sentence</div>
进而..
$('.box').each(function(i, box) {
var width = $(box).width(),
height = $(box).height(),
html = '<span style="white-space:nowrap">',
line = $(box).wrapInner(html).children()[0],
maxSizePX = 2000;
$(box).css('font-size', maxSizePX);
var widthFontSize = Math.floor(width/$(line).width()*maxSizePX),
heightFontSize = Math.floor(height/$(line).height()*maxSizePX),
maximalFontSize = Math.min(widthFontSize, heightFontSize, maxSizePX);
$(box).css('font-size', maximalFontSize);
$(box).text($(line).text());
});
见小提琴
我制作了(还)另一个插件来解决这个问题:
https://github.com/jeremiahrose/perfectFit.js
它生成 SVG,因此速度非常快 - 只需在页面加载时运行一次。 能够自动包装和缩放单个单词以完全适合 div。
我不知道如何将其添加到 sworoc 的帖子中,但我想无论如何我都会分享:如果您使用任何类型的 AJAX 导航,Lonesomeday 的解决方案就会变得一团糟。 我稍微修改为:
if ($('#hidden-resizer').length == 0){
$('<div />', {id: 'hidden-resizer'}).hide().appendTo(document.body);
}
这是我的解决方案:我在提供的 div 中测量新 div 中的文本,以便应该继承样式。 然后我将文本插入带有跨度的 div 以设置字体大小。 它将最大化为默认字体大小,但会缩小以适应。
它不会循环:在直接绘制到提供的 div 之前,它只在一次性 div 中绘制一次文本。 参见@Hoffmann 的回答——我只是不喜欢用一个完整的“插件”来回答这个问题。
需要jquery。
var txt = txt || {}
txt.pad_factor = 1.1;
txt.insertText_shrinkToFit = function(div,text)
{
var d = txt.cache || $('<div></div>');
txt.cache = d;
d.css('white-space','nowrap');
d.css('position','absolute');
d.css('top','-10000px');
d.css('font-size','1000px');
var p = $(div);
var max_w = parseInt(p.css('max-width')) || p.width();
var max_h = parseInt(p.css('font-size'));
p.append(d);
d.html(text);
var w = d.width() * txt.pad_factor;
d.remove();
var h = Math.floor(max_w*1000/w);
var s = ( max_h < h ? max_h : h ) + "px";
p.html('<SPAN style="font-size:' + s + '">' + text + '</SPAN>');
}
例如:
<html><head><script src=http://code.jquery.com/jquery-latest.min.js></script>
<script>/*insert code, from above, here.*/</script></head><body>
<div id=mysmalldiv style="max-width:300px;font-size:50px"></div>
<script>
txt.insertText_shrinkToFit("#mysmalldiv","My super long text for this div.");
</script>
</body></html>
测试:这就是我发现我需要 1.1 pad_factor 的方式; 您可以根据自己的需要进行调整。
<div id=mytestdiv style="max-width:300px;font-size:50px"></div>
<script>
var t = "my text ";
var i = 0;
var f = function() {
t += i + " ";
txt.insertText_shrinkToFit("#mytestdiv",t);
i++;
if(i < 100)
setTimeout(f,1000);
}
f();
</script>
注意:这是假设 px 字体大小。 我还没有用 em 或 pt 测试过。
对于纯 CSS 中的单行文本,例如标题等,有一种很好的方法可以做到这一点:
h1{
font-size: 4.5vw;
margin: 0 0 0 0;
line-height: 1em;
height: 1em;
}
h1:after{
content:"";
display: inline-block;
width: 100%;
}
确保您的字体大小保持足够小以保持标题 1 行。 使用“vw”(视口宽度)而不是“px”可以很容易地做到这一点并同时进行缩放。 当您将浏览器窗口设置得很大时,视口宽度往往会变得令人讨厌,许多站点使用它来将站点在真正宽的屏幕上保持在一定的宽度以下:
body{
max-width: 820px;
margin: 0 auto;
}
要确保您的字体不基于站点其余部分停止缩放后视口窗口的大小,请使用以下命令:
@media(min-width:820px){
h1{
font-size: 30px;
}
}
你可以做很多事情,比如
overflow:hidden
这减少了额外的线
overflow:auto
// 显示滚动条
看到这个
http://www.w3schools.com/Css/pr_pos_overflow.asp
尝试这样做//检查文本的长度
if($('#idfortext').length>sometthing)
{
var fontsize=10;
}
$('#yourid').css('font-size',fontsize)
我不确定是否有任何准确的方法来测量以像素为单位的文本宽度(这是您真正要寻找的问题根源),因为每个浏览器可能会以不同的方式显示字体。 除了根据句子中的字母数进行一些“模糊”调整外,您可能还想尝试使用此 CSS 代码。 您可以尝试使用固定宽度的字体(或样式)来显示文本,以便每个字符占用相同的空间。 这样,您可以做出最好的猜测,如果需要,CSS 至少会在裁剪文本之前给您一个漂亮的“...”。
.truncate
{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
这是我今天发现的:
测量文本容器的宽度 (w) 高度 (h) 并除以字体大小 (f):
iw = w/f
ih = h/f
将主容器宽度 (W) 除以 iw,将主容器高度 (H) 除以 ih:
kw = W/iw
kh = H/ih
在 kw 和 kh 之间选择最低的:这是想要的 FontSize。
https://jsfiddle.net/pinkynrg/44ua56dv/
function maximizeFontSize($target) {
var testingFont = 1000;
$target.find(".text-wrapper").css("font-size", testingFont+"px");
var textWidth = $(".text-wrapper").width()/1000;
var textHeight = $(".text-wrapper").height()/1000;
var width = $(".container").width();
var height = $(".container").height();
var kWidth = width/textWidth;
var kHeight = height/textHeight;
var fontSize = kWidth < kHeight ? kWidth : kHeight;
// finally
$(".text-wrapper")
.css("font-size", fontSize+"px")
.css("line-height", height+"px");
}
我正在使用香草 js。 一个对我改变水平尺寸有用的解决方案是,当我创建 div 时,我为给定的宽度设置了默认字体大小 %。 就我而言,我将 div 包装在一个更大的类中,但出于这些目的,您可以使用:
document.getElementById("mydiv").fontScale = {scaleVal: scaleFactor, defaultWidth: defaultWidth}
scaleFactor 是给定宽度(默认宽度)所需的字体大小(百分比)。 然后当我收到调整大小事件时:
let myDiv = document.getElementById("mydiv");
let width = myDiv.offsetWidth;
myDiv.style[fontSize] = String(width/myDiv.fontScale.defaultWidth * myDiv.fontScale.scaleFactor * 100) + "%";
我在这里写了几篇文章,并用它制作了一个 jQuery 插件。 我发现从底部开始向上的性能不是很好,所以我假设当前的字体大小很接近,并从那里开始工作。
$.fn.fitTextToWidth = function(desiredWidth) {
// In this method, we want to start at the current width and grow from there, assuming that we are close to the desired size already.
var $el = $(this);
var resizer = $('<'+$el.get(0).tagName+' />').css({'vsibility':'hidden','position':'absolute','left':'-9999px','display':'inline'}).html($el.html());
resizer.appendTo(document.body);
var size = parseInt($el.css('font-size'));
resizer.css('font-size',size+'px');
var growing = desiredWidth > resizer.width() ? true : false;
var adder = growing ? 1 : -1;
do {
size += adder;
resizer.css('font-size',size+'px');
} while(((growing && resizer.width()<desiredWidth) || (!growing && resizer.width()>desiredWidth)) && size>10 && size<100);
if (growing)
size -= 2; //we never want to go over
resizer.remove();
$el.css('font-size',size+'px');
}
// Example use:
$('#main h1').fitTextToWidth(350);
唯一的问题是它假定元素的 CSS 是全局的,并且只应用于元素类型。 换句话说,它创建一个同名的标签 in 并假设它与我们要更改的元素具有相同的 CSS 属性。 如果这对您来说不正确,只需修改创建resizer
的行。
适合容器宽度和高度的插件
简单的解决方案
<div class="fitt-text"><span>text</span></div>
js
$(".fitt-text").css('font-size', '1vw');
var cw = $(".fitt-text").width();
var w = $(".fitt-text span").width();
var f = cw/w;
$(".fitt-text").css('font-size', f + 'vw');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.