簡體   English   中英

JavaScript 縮放文本以適應固定的 Div

[英]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

它測量並計算適合文本的每個字母的大小不變度量,並使用它來計算適合文本到容器中的下一個最佳字體大小。

計算被緩存,這使得它在處理多個文本或必須多次適應文本時非常快(從第二次調整大小開始實際上沒有性能影響),例如在窗口調整大小時。

生產示例,擬合 14x16x2 文本

這是我對@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; 
} 

這是我今天發現的:

  1. 為目標文本設置一個非常大的假字體大小(f)
  2. 測量文本容器的寬度 (w) 高度 (h) 並除以字體大小 (f):

    • iw = w/f
    • ih = h/f
  3. 將主容器寬度 (W) 除以 iw,將主容器高度 (H) 除以 ih:

    • kw = W/iw
    • kh = H/ih
  4. 在 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的行。

適合容器寬度和高度的插件

http://blissitec.github.io/scaletextjs/

簡單的解決方案

<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM