Tính chiều rộng văn bản với JavaScript


467

Tôi muốn sử dụng JavaScript để tính độ rộng của chuỗi. Điều này là có thể mà không cần phải sử dụng một kiểu chữ đơn cách?

Nếu nó không được tích hợp sẵn, ý tưởng duy nhất của tôi là tạo một bảng chiều rộng cho mỗi ký tự, nhưng điều này khá bất hợp lý, đặc biệt là hỗ trợ Unicode và các kích cỡ loại khác nhau (và tất cả các trình duyệt cho vấn đề đó).


10
Xin lưu ý rằng nếu bạn đang sử dụng phông chữ bên ngoài, bạn sẽ phải sử dụng các kỹ thuật bên dưới sau khi chúng được tải. Bạn có thể không nhận ra điều này nếu bạn đã lưu chúng vào bộ nhớ cache hoặc nếu bạn đã cài đặt phiên bản cục bộ.
Seth W. Klein

Câu trả lời:


355

Tạo một DIV theo kiểu với các kiểu sau. Trong JavaScript của bạn, đặt kích thước phông chữ và thuộc tính mà bạn đang cố đo, đặt chuỗi của bạn vào DIV, sau đó đọc chiều rộng và chiều cao hiện tại của DIV. Nó sẽ kéo dài để phù hợp với nội dung và kích thước sẽ nằm trong một vài pixel của kích thước được hiển thị chuỗi.

var fontSize = 12;
var test = document.getElementById("Test");
test.style.fontSize = fontSize;
var height = (test.clientHeight + 1) + "px";
var width = (test.clientWidth + 1) + "px"

console.log(height, width);
#Test
{
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap; /* Thanks to Herb Caudill comment */
}
<div id="Test">
    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
</div>


8
Điều duy nhất tôi muốn thêm là điều này có thể cung cấp kích thước sai tùy thuộc vào kiểu được sử dụng. Hãy nhớ rằng bạn có thể có các kiểu như p {letter-distance: 0.1em; } rằng một phần tử DIV sẽ không phản ánh. Bạn phải đảm bảo rằng các kiểu tại chỗ phù hợp với nơi bạn sẽ sử dụng văn bản.
Jim

5
Nhận xét của Ditto Jim - kiểm tra kỹ để đảm bảo container, div trong trường hợp này, không có bất kỳ kiểu nào khác được áp dụng cho nó thông qua các quy tắc lựa chọn css mà bạn có thể không nhận thức được tại thời điểm đó. Loại bỏ tất cả các kiểu có liên quan từ thùng chứa trước khi áp dụng những kiểu bạn quan tâm trước khi đo.
Jason Bunting

44
Bạn cũng nên đặt trong khoảng trắng: nowrap nếu bạn nghĩ rằng văn bản sẽ vượt quá chiều rộng của trình duyệt.
Herb Caudill

5
@BBog tất cả những gì hack xung quanh là lý do tại sao tôi đề xuất một cách tiếp cận khác, ít hack hơn, ở tầng dưới. Hãy xem nó ở đây .
Domi

11
Chỉ tò mò những gì +1được cho trên mỗi chiều?
Kip

385

Trong HTML 5 , bạn chỉ có thể sử dụng phương thức Canvas.measureText (giải thích thêm tại đây ).

Hãy thử câu đố này :

/**
 * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
 * 
 * @param {String} text The text to be rendered.
 * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
 * 
 * @see /programming/118241/calculate-text-width-with-javascript/21015393#21015393
 */
function getTextWidth(text, font) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
}

console.log(getTextWidth("hello there!", "bold 12pt arial"));  // close to 86

Fiddle này so sánh phương thức Canvas này với một biến thể của phương pháp dựa trên DOM của Bob Monteverde , do đó bạn có thể phân tích và so sánh độ chính xác của kết quả.

Có một số lợi thế của phương pháp này, bao gồm:

  • Ngắn gọn và an toàn hơn các phương thức khác (dựa trên DOM) vì nó không thay đổi trạng thái toàn cầu, chẳng hạn như DOM của bạn.
  • Có thể tùy chỉnh thêm bằng cách sửa đổi nhiều thuộc tính văn bản canvas , như textAligntextBaseline.

LƯU Ý: Khi bạn thêm văn bản vào DOM, hãy nhớ cũng tính đến phần đệm, lề và viền .

CHÚ THÍCH 2: Trên một số trình duyệt, phương pháp này mang lại độ chính xác của pixel phụ (kết quả là số dấu phẩy động), trên các trình duyệt khác thì không (kết quả chỉ là một int). Bạn có thể muốn chạy Math.floor(hoặc Math.ceil) trên kết quả, để tránh sự không nhất quán. Do phương thức dựa trên DOM không bao giờ chính xác là pixel phụ, nên phương thức này thậm chí còn có độ chính xác cao hơn các phương thức khác ở đây.

Theo jsperf này (nhờ những người đóng góp trong các bình luận), phương thức Canvasphương thức dựa trên DOM có tốc độ nhanh như nhau, nếu bộ đệm được thêm vào phương thức dựa trên DOM và bạn không sử dụng Firefox. Trong Firefox, vì một số lý do, phương thức Canvas này nhanh hơn nhiều so với phương thức dựa trên DOM (tính đến tháng 9 năm 2014).


7
Đây là một lựa chọn tuyệt vời, tôi không biết về nó. Bạn đã bao giờ so sánh hiệu suất của việc này với hiệu suất đo trong DOM chưa?
SimplGy

2
Tôi đã thêm bộ đệm vào điểm chuẩn jsperf đó. Bây giờ hai phương thức khá nhiều trên mệnh: jsperf.com/measure-text- thong/4
Brandon Bloom

1
@Martin Hả? "Nhiều yếu tố HTML" có liên quan gì ở đây? Đối tượng canvas trong ví dụ này thậm chí không được gắn vào DOM. Và thậm chí bên cạnh đó, việc thay đổi phông chữ trong bối cảnh vẽ canvas thậm chí không ảnh hưởng đến canvas cho đến khi bạn strokeText()hoặc fillText(). Có lẽ bạn muốn bình luận về một câu trả lời khác nhau?
Ajedi32

1
Giải pháp tốt đẹp. Tôi đã kết hợp một vài phương thức khác xung quanh câu trả lời của Domi để tôi có thể - Lấy một chuỗi bị cắt (có khả năng) có dấu chấm lửng (...) ở cuối nếu nó không vừa trong một không gian nhất định (nhiều như chuỗi như có thể sẽ được sử dụng) - Truyền vào Phần tử JQuery có chứa chuỗi (có thể bị cắt ngắn) và xác định động các thuộc tính Phông để chúng không bị mã hóa cứng, cho phép các thuộc tính phông chữ CSS thay đổi mà không bị phá vỡ cách bố trí. JSFiddle Tại đây: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey

2
Tốt vì người dùng không nhìn thấy nó!
clabe45

110

Đây là một cái tôi đã đánh với nhau mà không có ví dụ. Có vẻ như tất cả chúng ta đều trên cùng một trang.

String.prototype.width = function(font) {
  var f = font || '12px arial',
      o = $('<div></div>')
            .text(this)
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
            .appendTo($('body')),
      w = o.width();

  o.remove();

  return w;
}

Sử dụng nó rất đơn giản: "a string".width()

** Đã thêm các white-space: nowrapchuỗi có chiều rộng lớn hơn chiều rộng cửa sổ có thể được tính toán.


2
Cảm ơn JordanC. Một điều tôi muốn nói thêm là, nếu bạn gọi điều này rất nhiều lần trên cùng một trang và hiệu suất là một vấn đề, bạn có thể duy trì DIV, và chỉ cần thay đổi nội dung và kiểm tra độ rộng. Tôi chỉ làm theo cách này để một khi mọi thứ được nói và thực hiện, DOM sẽ giống như khi bạn bắt đầu
Bob Monteverde

3
Tôi sẽ không thêm phương thức này vào Stringvì nó làm giảm sự phân tách mối quan tâm của chương trình của bạn (mã lõi riêng biệt so với mã UI). Hãy tưởng tượng bạn muốn chuyển mã lõi của mình sang một nền tảng với khung UI rất khác ...
Domi

23
Đây là thiết kế tồi , nó không chỉ kết hợp mô hình của bạn với chế độ xem mà còn kết hợp trực tiếp với jQuery. Trên hết, đây là địa ngục phản xạ, điều này chắc chắn sẽ không có quy mô tốt.
James

1
Nếu bạn muốn giá trị float, bạn có thể sử dụng o[0].getBoundingClientRect().widthnhư được đề xuất tại đây: stackoverflow.com/a/16072668/936397
Alexander Olsson

1
@virus cũng nói hơn 100 người có thể không quan tâm đến hiệu suất ... Tuy nhiên, không làm cho những gì tôi nói ít hợp lệ hoặc đúng.
James

30

jQuery:

(function($) {

 $.textMetrics = function(el) {

  var h = 0, w = 0;

  var div = document.createElement('div');
  document.body.appendChild(div);
  $(div).css({
   position: 'absolute',
   left: -1000,
   top: -1000,
   display: 'none'
  });

  $(div).html($(el).html());
  var styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing'];
  $(styles).each(function() {
   var s = this.toString();
   $(div).css(s, $(el).css(s));
  });

  h = $(div).outerHeight();
  w = $(div).outerWidth();

  $(div).remove();

  var ret = {
   height: h,
   width: w
  };

  return ret;
 }

})(jQuery);

27

Điều này làm việc cho tôi ...

// Handy JavaScript to measure the size taken to render the supplied text;
// you can supply additional style information too if you have it.

function measureText(pText, pFontSize, pStyle) {
    var lDiv = document.createElement('div');

    document.body.appendChild(lDiv);

    if (pStyle != null) {
        lDiv.style = pStyle;
    }
    lDiv.style.fontSize = "" + pFontSize + "px";
    lDiv.style.position = "absolute";
    lDiv.style.left = -1000;
    lDiv.style.top = -1000;

    lDiv.innerHTML = pText;

    var lResult = {
        width: lDiv.clientWidth,
        height: lDiv.clientHeight
    };

    document.body.removeChild(lDiv);
    lDiv = null;

    return lResult;
}

Xin chào câu trả lời của bạn thực sự hữu ích tuy nhiên hãy sử dụng .cssText thay vì .style để hỗ trợ IE 8 trở xuống ..
Dilip Rajkumar

Câu trả lời này rất hay, nhưng khi tôi tạo ra một đoạn văn bản lớn, thì nó trở thành một vài pixel không chính xác. Có phải vì chiều rộng không phải là số nguyên?
Bussyroopo

20

Các ExtJS javascript thư viện có một lớp lớn được gọi là Ext.util.TextMetrics rằng "cung cấp phép đo điểm ảnh chính xác cho khối văn bản để bạn có thể xác định chính xác có bao cao và rộng, tính theo pixel, một khối nhất định của văn bản sẽ được". Bạn có thể sử dụng trực tiếp hoặc xem nguồn của nó để mã để xem cách thực hiện.

http://docs.sencha.com/extjs/6.5.3/modern/Ext.util.TextMetrics.html


1
ExtJS có một giấy phép kỳ lạ. Bạn phải trả cho những người bảo trì hiện tại, Công ty Sencha để sử dụng nó hoặc bạn phải mã nguồn mở tất cả các mã liên quan trong ứng dụng của bạn. Đây là một điểm dừng chương trình cho hầu hết các công ty. jQuery, mặt khác, sử dụng giấy phép MIT rất dễ cho phép.
devdanke

1
Không javascript tự động đáp ứng các yêu cầu của nguồn mở? Bạn phục vụ nguồn cho bất cứ ai xem trang.
PatrickO

10
Có một sự khác biệt giữa việc có thể xem mã nguồn và nguồn mở, được xác định bằng cấp phép.
Parker Ault

Cảm ơn những người trong chúng ta vẫn đang sử dụng ExtJS :-)
Monarch Wadia

1
bạn nên để ExtJS yên nghỉ
canbax

19

Tôi thích "ý tưởng duy nhất" của bạn về việc chỉ làm một bản đồ chiều rộng ký tự tĩnh! Nó thực sự hoạt động tốt cho mục đích của tôi. Đôi khi, vì lý do hiệu suất hoặc vì bạn không có quyền truy cập dễ dàng vào DOM, bạn có thể chỉ muốn một máy tính độc lập hacky nhanh chóng được hiệu chỉnh theo một phông chữ duy nhất. Vì vậy, đây là một trong những hiệu chuẩn để Helvetica; truyền một chuỗi và (tùy chọn) một cỡ chữ:

function measureText(str, fontSize = 10) {
  const widths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625]
  const avg = 0.5279276315789471
  return str
    .split('')
    .map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
    .reduce((cur, acc) => acc + cur) * fontSize
}

Mảng xấu xí khổng lồ đó là độ rộng ký tự ASCII được lập chỉ mục theo mã ký tự. Vì vậy, điều này chỉ hỗ trợ ASCII (nếu không, nó giả sử độ rộng ký tự trung bình). May mắn thay, chiều rộng về cơ bản tỷ lệ tuyến tính với kích thước phông chữ, vì vậy nó hoạt động khá tốt ở bất kỳ kích thước phông chữ nào. Đáng chú ý là thiếu bất kỳ nhận thức về k sâu hoặc chữ hoặc bất cứ điều gì.

Để "hiệu chỉnh", tôi chỉ hiển thị mọi ký tự lên charCode 126 (dấu ngã mạnh mẽ) trên một svg và lấy hộp giới hạn và lưu nó vào mảng này; thêm mã và giải thích và demo ở đây .


1
đó là một giải pháp thông minh, một giải pháp hay :) Tôi luôn sử dụng cùng một phông chữ / kích thước, vì vậy nó rất phù hợp với tôi. Tôi thấy hiệu suất của các giải pháp DOM / Canvas là một vấn đề thực sự, điều này thực sự rõ ràng, chúc mừng!
mikeapr4

1
loại bỏ sự cần thiết của canvas +1
frage

Bạn có thể thoát khỏi * fontSizevà chỉ cần sử dụng 'em'
Matt Fletcher

Thật là một câu trả lời tuyệt vời!
almosnow


7

Bạn có thể sử dụng canvas để không phải xử lý nhiều thuộc tính css:

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.font = "20pt Arial";  // This can be set programmaticly from the element's font-style if desired
var textWidth = ctx.measureText($("#myElement").text()).width;

Không phải là nặng hơn nhiều (với bối cảnh 2d, v.v.) hơn là tạo một phần tử DOM và chỉ định các thuộc tính css cho nó?
Pharao2k

1
Đây là một cách tiếp cận rõ ràng nếu bạn đang sử dụng canvas cho một cái gì đó. Nhưng RẤT RẤT. Chỉ riêng cuộc gọi đo lường mất khoảng 8-10 ms (sử dụng Chrome).
Rui Marques

6
<span id="text">Text</span>

<script>
var textWidth = document.getElementById("text").offsetWidth;
</script>

Điều này sẽ hoạt động miễn là thẻ <span> không có kiểu nào khác được áp dụng cho nó. offsetWidth sẽ bao gồm chiều rộng của bất kỳ đường viền, đệm ngang, chiều rộng thanh cuộn dọc, v.v.


Đó là ít nhiều những gì tạo ra các giải pháp trên, nhưng vì văn bản của bạn có thể được chia thành nhiều dòng, họ thêm một số kiểu CSS vào văn bản để có được chiều rộng văn bản thực sự.
Adrian Maire

2

Đoạn mã bên dưới, "tính toán" độ rộng của thẻ span, nối thêm "..." cho nó nếu nó quá dài và làm giảm độ dài văn bản, cho đến khi nó khớp với cha mẹ của nó (hoặc cho đến khi nó đã thử nhiều hơn một ngàn lần)

CSS

div.places {
  width : 100px;
}
div.places span {
  white-space:nowrap;
  overflow:hidden;
}

HTML

<div class="places">
  <span>This is my house</span>
</div>
<div class="places">
  <span>And my house are your house</span>
</div>
<div class="places">
  <span>This placename is most certainly too wide to fit</span>
</div>

JavaScript (với jQuery)

// loops elements classed "places" and checks if their child "span" is too long to fit
$(".places").each(function (index, item) {
    var obj = $(item).find("span");
    if (obj.length) {
        var placename = $(obj).text();
        if ($(obj).width() > $(item).width() && placename.trim().length > 0) {
            var limit = 0;
            do {
                limit++;
                                    placename = placename.substring(0, placename.length - 1);
                                    $(obj).text(placename + "...");
            } while ($(obj).width() > $(item).width() && limit < 1000)
        }
    }
});

2
Hãy thử tìm kiếm nhị phân thay vì lặp 1 ký tự một lần: xem nhận xét của tôi về câu trả lời của Alex cho stackoverflow.com/questions/536814/iêu
StanleyH

@StanleyH: Ý kiến ​​hay - Tôi sẽ thực hiện đề xuất của bạn càng sớm càng tốt.
Techek

2

Tốt hơn là phát hiện xem văn bản có phù hợp ngay trước khi bạn hiển thị phần tử hay không. Vì vậy, bạn có thể sử dụng chức năng này mà không yêu cầu phần tử phải ở trên màn hình.

function textWidth(text, fontProp) {
    var tag = document.createElement("div");
    tag.style.position = "absolute";
    tag.style.left = "-999em";
    tag.style.whiteSpace = "nowrap";
    tag.style.font = fontProp;
    tag.innerHTML = text;

    document.body.appendChild(tag);

    var result = tag.clientWidth;

    document.body.removeChild(tag);

    return result;
}

Sử dụng:

if ( textWidth("Text", "bold 13px Verdana") > elementWidth) {
    ...
}

2

Trong trường hợp bất kỳ ai khác đến đây đều tìm cách đo chiều rộng của chuỗi cách để biết cỡ chữ lớn nhất sẽ phù hợp với chiều rộng cụ thể, đây là một hàm xây dựng trên giải pháp của @ Domi với tìm kiếm nhị phân :

/**
 * Find the largest font size (in pixels) that allows the string to fit in the given width.
 * 
 * @param {String} text The text to be rendered.
 * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold ?px verdana") -- note the use of ? in place of the font size.
 * @param {width} the width in pixels the string must fit in
 * @param {minFontPx} the smallest acceptable font size in pixels
 * @param {maxFontPx} the largest acceptable font size in pixels
**/
function GetTextSizeForWidth( text, font, width, minFontPx, maxFontPx )
{
    for ( ; ; )
    {
        var s = font.replace( "?", maxFontPx );
        var w = GetTextWidth( text, s );
        if ( w <= width )
        {
            return maxFontPx;
        }

        var g = ( minFontPx + maxFontPx ) / 2;

        if ( Math.round( g ) == Math.round( minFontPx ) || Math.round( g ) == Math.round( maxFontPx ) )
        {
            return g;
        }

        s = font.replace( "?", g );
        w = GetTextWidth( text, s );
        if ( w >= width )
        {
            maxFontPx = g;
        }
        else
        {
            minFontPx = g;
        }
    }
}

Điều này hoạt động thật tuyệt vời (kết hợp với mã từ câu trả lời của Domi)
r3wt

1

Hãy thử mã này:

function GetTextRectToPixels(obj)
{
var tmpRect = obj.getBoundingClientRect();
obj.style.width = "auto"; 
obj.style.height = "auto"; 
var Ret = obj.getBoundingClientRect(); 
obj.style.width = (tmpRect.right - tmpRect.left).toString() + "px";
obj.style.height = (tmpRect.bottom - tmpRect.top).toString() + "px"; 
return Ret;
}

1

Chiều rộng và chiều cao của văn bản có thể được lấy bằng clientWidthclientHeight

var element = document.getElementById ("mytext");

var width = element.clientWidth;
var height = element.clientHeight;

đảm bảo rằng thuộc tính vị trí kiểu được đặt thành tuyệt đối

element.style.position = "absolute";

không bắt buộc phải ở bên trong a div, có thể ở bên trong a phoặc aspan


1

Dựa trên câu trả lời của Deepak Nadar , tôi đã thay đổi tham số chức năng để chấp nhận kiểu văn bản và phông chữ. Bạn không cần phải tham khảo một yếu tố. Ngoài ra, fontOptionscó mặc định, vì vậy bạn không cần phải cung cấp tất cả chúng.

(function($) {
  $.format = function(format) {
    return (function(format, args) {
      return format.replace(/{(\d+)}/g, function(val, pos) {
        return typeof args[pos] !== 'undefined' ? args[pos] : val;
      });
    }(format, [].slice.call(arguments, 1)));
  };
  $.measureText = function(html, fontOptions) {
    fontOptions = $.extend({
      fontSize: '1em',
      fontStyle: 'normal',
      fontWeight: 'normal',
      fontFamily: 'arial'
    }, fontOptions);
    var $el = $('<div>', {
      html: html,
      css: {
        position: 'absolute',
        left: -1000,
        top: -1000,
        display: 'none'
      }
    }).appendTo('body');
    $(fontOptions).each(function(index, option) {
      $el.css(option, fontOptions[option]);
    });
    var h = $el.outerHeight(), w = $el.outerWidth();
    $el.remove();
    return { height: h, width: w };
  };
}(jQuery));

var dimensions = $.measureText("Hello World!", { fontWeight: 'bold', fontFamily: 'arial' });

// Font Dimensions: 94px x 18px
$('body').append('<p>').text($.format('Font Dimensions: {0}px x {1}px', dimensions.width, dimensions.height));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


0

Tôi đoán điều này tương tự như mục Depak, nhưng dựa trên tác phẩm của Louis Lazaris được xuất bản tại một bài báo trên trang ấn tượng

(function($){

        $.fn.autofit = function() {             

            var hiddenDiv = $(document.createElement('div')),
            content = null;

            hiddenDiv.css('display','none');

            $('body').append(hiddenDiv);

            $(this).bind('fit keyup keydown blur update focus',function () {
                content = $(this).val();

                content = content.replace(/\n/g, '<br>');
                hiddenDiv.html(content);

                $(this).css('width', hiddenDiv.width());

            });

            return this;

        };
    })(jQuery);

Sự kiện phù hợp được sử dụng để thực hiện lệnh gọi hàm inmediatly sau khi hàm được liên kết với điều khiển.

ví dụ: $ ('input'). autofit (). trigger ("fit");


0

Không có jQuery:

String.prototype.width = function (fontSize) {
    var el,
        f = fontSize + " px arial" || '12px arial';
    el = document.createElement('div');
    el.style.position = 'absolute';
    el.style.float = "left";
    el.style.whiteSpace = 'nowrap';
    el.style.visibility = 'hidden';
    el.style.font = f;
    el.innerHTML = this;
    el = document.body.appendChild(el);
    w = el.offsetWidth;
    el.parentNode.removeChild(el);
    return w;
}

// Usage
"MyString".width(12);

Khi bạn đặt một số không hoạt động, bởi vì không có không gian, nếu bạn loại bỏ nó, nó sẽ hoạt động tốt: fontSize + "px arial" -> fontSize + "px arial", chỉ vậy thôi.
Alberto Acuña

0

Ví dụ về ví dụ làm việc: http://jsfiddle.net/tdpLdqpo/1/

HTML:

<h1 id="test1">
    How wide is this text?
</h1>
<div id="result1"></div>
<hr/>
<p id="test2">
    How wide is this text?
</p>
<div id="result2"></div>
<hr/>
<p id="test3">
    How wide is this text?<br/><br/>
    f sdfj f sdlfj lfj lsdk jflsjd fljsd flj sflj sldfj lsdfjlsdjkf sfjoifoewj flsdjfl jofjlgjdlsfjsdofjisdojfsdmfnnfoisjfoi  ojfo dsjfo jdsofjsodnfo sjfoj ifjjfoewj fofew jfos fojo foew jofj s f j
</p>
<div id="result3"></div>

Mã JavaScript:

function getTextWidth(text, font) {
    var canvas = getTextWidth.canvas ||
        (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
};

$("#result1")
.text("answer: " +
    getTextWidth(
             $("#test1").text(),
             $("#test1").css("font")) + " px");

$("#result2")
    .text("answer: " +
        getTextWidth(
             $("#test2").text(),
             $("#test2").css("font")) + " px");

$("#result3")
    .text("answer: " +
        getTextWidth(
             $("#test3").text(),
             $("#test3").css("font")) + " px");

0

Các Element.getClientRects()phương thức trả về một tập hợp các DOMRectđối tượng mà chỉ ra hình chữ nhật bounding cho mỗi hộp biên giới CSS trong một khách hàng. Giá trị được trả về là một tập hợp các DOMRectđối tượng, một đối tượng cho mỗi hộp viền CSS được liên kết với phần tử. Mỗi DOMRectđối tượng chứa read-only left, top, rightbottomcác thuộc tính mô tả hộp biên giới, tính theo pixel, với thân nhân trên bên trái để phía trên cùng bên trái của khung nhìn.

Element.getClientRects () của Mozilla Người đóng góp được cấp phép theo CC-BY-SA 2.5 .

Tổng hợp tất cả các chiều rộng hình chữ nhật được trả về mang lại tổng chiều rộng văn bản tính bằng pixel.

document.getElementById('in').addEventListener('input', function (event) {
    var span = document.getElementById('text-render')
    span.innerText = event.target.value
    var rects = span.getClientRects()
    var widthSum = 0
    for (var i = 0; i < rects.length; i++) {
        widthSum += rects[i].right - rects[i].left
    }
    document.getElementById('width-sum').value = widthSum
})
<p><textarea id='in'></textarea></p>
<p><span id='text-render'></span></p>
<p>Sum of all widths: <output id='width-sum'>0</output>px</p>


0

Tôi đã tạo một mô-đun ES6 nhỏ (sử dụng jQuery):

import $ from 'jquery';

const $span=$('<span>');
$span.css({
    position: 'absolute',
    display: 'none'
}).appendTo('body');

export default function(str, css){
    $span[0].style = ''; // resetting the styles being previously set
    $span.text(str).css(css || {});
    return $span.innerWidth();
}

Dễ sử dụng:

import stringWidth from './string_width';
const w = stringWidth('1-3', {fontSize: 12, padding: 5});

Điều thú vị mà bạn có thể nhận thấy - nó cho phép tính đến mọi thuộc tính CSS, thậm chí cả phần đệm!


0

Bạn cũng có thể làm điều này với createdRange, chính xác hơn so với kỹ thuật nhân bản văn bản:

function getNodeTextWidth(nodeWithText) {
    var textNode = $(nodeWithText).contents().filter(function () {
        return this.nodeType == Node.TEXT_NODE;
    })[0];
    var range = document.createRange();
    range.selectNode(textNode);
    return range.getBoundingClientRect().width;
}

-1
var textWidth = (function (el) {
    el.style.position = 'absolute';
    el.style.top = '-1000px';
    document.body.appendChild(el);

    return function (text) {
        el.innerHTML = text;
        return el.clientWidth;
    };
})(document.createElement('div'));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.