Hitung lebar teks dengan JavaScript

467

Saya ingin menggunakan JavaScript untuk menghitung lebar string. Apakah ini mungkin tanpa harus menggunakan jenis huruf monospace?

Jika tidak built-in, satu-satunya ide saya adalah membuat tabel lebar untuk setiap karakter, tetapi ini sangat tidak masuk akal terutama mendukung Unicode dan ukuran tipe yang berbeda (dan semua browser dalam hal ini).

Yakub
sumber
10
Berhati-hatilah jika Anda menggunakan font eksternal, Anda harus menggunakan teknik di bawah ini setelah mereka dimuat. Anda mungkin tidak menyadari hal ini jika di-cache atau menginstal versi lokal.
Seth W. Klein

Jawaban:

355

Buat DIV yang ditata dengan gaya berikut. Di JavaScript Anda, atur ukuran font dan atribut yang Anda coba ukur, masukkan string Anda ke DIV, lalu baca lebar dan tinggi DIV saat ini. Itu akan meregang agar sesuai dengan konten dan ukurannya akan berada dalam beberapa piksel dari ukuran string yang diberikan.

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>

CMPalmer
sumber
8
Satu-satunya hal yang saya tambahkan adalah bahwa ini dapat memberikan dimensi yang salah tergantung pada gaya yang digunakan. Ingat Anda mungkin memiliki gaya seperti p {letter-spacing: 0.1em; } bahwa elemen DIV tidak akan mencerminkan. Anda harus memastikan bahwa gaya pada tempatnya sesuai untuk tempat Anda akan menggunakan teks.
Jim
5
Komentar Ditto Jim - periksa untuk memastikan wadah, div dalam hal ini, tidak memiliki gaya lain yang diterapkan melalui aturan pemilihan css yang mungkin tidak Anda sadari pada saat itu. Lepaskan semua gaya yang relevan dari wadah sebelum menerapkan yang Anda pedulikan sebelum mengukur.
Jason Bunting
44
Anda juga harus meletakkan dalam ruang putih: nowrap jika Anda berpikir teks akan melebihi lebar browser.
Herb Caudill
5
@Bog semua peretasan di sekitar itu sebabnya saya menyarankan pendekatan yang berbeda, kurang peretasan, turun. Lihatlah di sini .
Domi
11
Hanya ingin tahu untuk apa +1pada setiap dimensi?
Kip
385

Di HTML 5 , Anda bisa menggunakan metode Canvas.measureText (penjelasan lebih lanjut di sini ).

Coba biola ini :

/**
 * 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

Biola ini membandingkan metode Kanvas ini dengan variasi metode berbasis DOM Bob Monteverde , sehingga Anda dapat menganalisis dan membandingkan keakuratan hasil.

Ada beberapa keuntungan dari pendekatan ini, termasuk:

  • Lebih ringkas dan lebih aman daripada metode lain (berbasis DOM) karena tidak mengubah keadaan global, seperti DOM Anda.
  • Kustomisasi lebih lanjut dimungkinkan dengan memodifikasi lebih banyak properti teks kanvas , seperti textAligndan textBaseline.

CATATAN: Saat Anda menambahkan teks ke DOM Anda, ingatlah untuk juga memperhitungkan padding, margin, dan border .

CATATAN 2: Pada beberapa browser, metode ini menghasilkan akurasi sub-pixel (hasilnya adalah angka floating point), pada yang lain tidak (hasilnya hanya int). Anda mungkin ingin menjalankan Math.floor(atau Math.ceil) pada hasilnya, untuk menghindari inkonsistensi. Karena metode berbasis DOM tidak pernah akurat sub-pixel, metode ini bahkan memiliki presisi yang lebih tinggi daripada metode lain di sini.

Menurut jsperf ini (terima kasih kepada kontributor dalam komentar), metode Canvas dan metode berbasis DOM hampir sama cepatnya, jika caching ditambahkan ke metode berbasis DOM dan Anda tidak menggunakan Firefox. Di Firefox, untuk beberapa alasan, metode Canvas ini jauh lebih cepat daripada metode berbasis DOM (per September 2014).

Domi
sumber
7
Ini pilihan yang luar biasa, saya tidak tahu. Pernah membandingkan kinerja ini dengan kinerja pengukuran di DOM?
SimplGy
2
Saya menambahkan caching ke tolok ukur jsperf itu. Sekarang kedua metode ini cukup setara: jsperf.com/measure-text-width/4
Brandon Bloom
1
@ Martin Huh? Apa hubungan "banyak elemen HTML" dengan apa pun di sini? Objek kanvas dalam contoh ini bahkan tidak dilampirkan ke DOM. Dan terlepas dari itu, mengubah font dalam konteks menggambar kanvas bahkan tidak mempengaruhi kanvas sama sekali sampai Anda strokeText()atau fillText(). Mungkin Anda bermaksud mengomentari jawaban yang berbeda?
Ajedi32
1
Solusi yang bagus. Saya telah membungkus beberapa metode lain di sekitar jawaban Domi sehingga saya bisa - Dapatkan (berpotensi) string terpotong dengan ellipsis (...) di akhir jika tidak cocok di ruang tertentu (sebanyak string sedapat mungkin akan digunakan) - Lulus di Elemen JQuery yang berisi string (mungkin terpotong), dan tentukan atribut Font secara dinamis sehingga tidak harus dikodekan secara keras, yang memungkinkan atribut font CSS berubah tanpa merusak tata letak. JSFiddle Di Sini: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
Bagus karena pengguna tidak melihatnya!
clabe45
110

Inilah yang saya kocok bersama tanpa contoh. Sepertinya kita semua ada di halaman yang sama.

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;
}

Penggunaannya sederhana: "a string".width()

** Ditambahkan white-space: nowrapsehingga string dengan lebar lebih besar dari lebar jendela dapat dihitung.

Bob Monteverde
sumber
2
Terima kasih JordanC. Satu hal yang akan saya tambahkan adalah, jika Anda memanggil ini berkali-kali pada halaman yang sama, dan kinerja adalah masalah, Anda bisa bertahan DIV, dan hanya mengubah konten dan memeriksa lebar. Saya hanya melakukannya dengan cara ini sehingga setelah semuanya dikatakan dan dilakukan, DOM akan sama seperti ketika Anda mulai
Bob Monteverde
3
Saya tidak akan menambahkan metode ini Stringkarena mengurangi pemisahan kekhawatiran program Anda (kode inti terpisah vs kode UI). Bayangkan Anda ingin mem-porting kode inti Anda ke platform dengan kerangka UI yang sangat berbeda ...
Domi
23
Ini adalah desain yang buruk , tidak hanya memasangkan model Anda dengan tampilan Anda, tetapi juga memasangkannya secara langsung dengan jQuery. Di atas semua itu, ini adalah neraka neraka, ini pasti tidak akan skala dengan baik.
James
1
Jika Anda menginginkan nilai float, Anda dapat menggunakan o[0].getBoundingClientRect().widthseperti yang disarankan di sini: stackoverflow.com/a/16072668/936397
Alexander Olsson
1
@Virus baik mengatakan 100+ orang mungkin tidak peduli tentang kinerja juga ... Meskipun demikian, tidak membuat apa yang saya katakan kurang valid atau benar.
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);
Deepak Nadar
sumber
27

Ini bekerja untuk saya ...

// 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;
}
Pete
sumber
Hai jawaban Anda sangat membantu namun gunakan .cssText daripada .style untuk mendukung IE 8 dan lebih rendah ..
Dilip Rajkumar
Jawaban ini bagus, tetapi ketika saya menghasilkan sebagian besar teks, maka itu menjadi beberapa piksel tidak akurat. Apakah karena lebarnya bukan bilangan bulat?
Bobtroopo
20

The ExtJS javascript perpustakaan memiliki kelas besar yang disebut Ext.util.TextMetrics bahwa "menyediakan pengukuran pixel yang tepat untuk blok teks sehingga Anda dapat menentukan dengan tepat seberapa tinggi dan lebar, dalam pixel, blok diberikan teks akan". Anda dapat menggunakannya secara langsung atau melihat sumbernya ke kode untuk melihat bagaimana hal ini dilakukan.

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

lep besar
sumber
1
ExtJS memiliki lisensi aneh. Entah Anda membayar pengelola saat ini, Perusahaan Sencha untuk menggunakannya, atau Anda harus membuka sumber semua kode terkait dalam aplikasi Anda. Ini adalah penghenti acara bagi sebagian besar perusahaan. jQuery, di sisi lain, menggunakan lisensi MIT yang sangat permisif.
devdanke
1
Tidakkah javascript secara otomatis memenuhi persyaratan open source? Anda melayani sumber kepada siapa pun yang melihat halaman.
PatrickO
10
Ada perbedaan antara bisa melihat kode sumber dan sumber terbuka, yang ditentukan oleh lisensi.
Parker Ault
Terima kasih dari kita yang masih menggunakan ExtJS :-)
Monarch Wadia
1
Anda seharusnya membiarkan ExtJS beristirahat dengan tenang
canbax
19

Saya suka "satu-satunya ide" Anda hanya melakukan peta lebar karakter statis! Ini sebenarnya berfungsi dengan baik untuk tujuan saya. Terkadang, untuk alasan kinerja atau karena Anda tidak memiliki akses mudah ke DOM, Anda mungkin ingin kalkulator mandiri yang cepat dikalibrasi ke satu font. Jadi, inilah yang dikalibrasi ke Helvetica; meneruskan string dan (opsional) ukuran font:

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
}

Array jelek raksasa itu adalah lebar karakter ASCII yang diindeks oleh kode karakter. Jadi ini hanya mendukung ASCII (selain itu mengasumsikan lebar karakter rata-rata). Untungnya, lebar pada dasarnya berskala linier dengan ukuran font, sehingga berfungsi cukup baik pada ukuran font apa pun. Itu terasa kurang kesadaran tentang kerning atau ligatur atau apa pun.

Untuk "mengkalibrasi", saya hanya merender setiap karakter hingga charCode 126 (the perkasa tilde) pada svg dan mendapatkan kotak pembatas dan menyimpannya ke array ini; lebih banyak kode dan penjelasan dan demo di sini .

Toph
sumber
1
itu adalah solusi cerdas, bagus :) Saya selalu menggunakan font / ukuran yang sama, jadi sangat cocok untuk saya. Saya menemukan kinerja solusi DOM / Canvas masalah nyata, ini benar-benar bersih, tepuk tangan!
mikeapr4
1
menghilangkan kebutuhan untuk kanvas +1
frage
Anda dapat menyingkirkannya * fontSizedan gunakan saja 'em'
Matt Fletcher
Sungguh jawaban yang luar biasa!
almnow sekarang
11

Saya menulis alat kecil untuk itu. Mungkin bermanfaat bagi seseorang. Ini bekerja tanpa jQuery .

https://github.com/schickling/calculate-size

Pemakaian:

var size = calculateSize("Hello world!", {
   font: 'Arial',
   fontSize: '12px'
});

console.log(size.width); // 65
console.log(size.height); // 14

Fiddle: http://jsfiddle.net/PEvL8/

cekikikan
sumber
7

Anda dapat menggunakan kanvas sehingga Anda tidak perlu terlalu banyak berurusan dengan properti 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;
rysama
sumber
Bukankah itu jauh lebih berat (dengan mendapatkan konteks 2d dll) daripada membuat elemen DOM dan menentukan properti css untuk itu?
Pharao2k
1
Ini adalah pendekatan yang bersih jika Anda sudah menggunakan kanvas untuk sesuatu. Tapi sangat lambat. Panggilan MeasText saja membutuhkan sekitar 8-10 ms (menggunakan Chrome).
Rui Marques
6
<span id="text">Text</span>

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

Ini akan berfungsi selama tag <span> tidak memiliki gaya lain yang diterapkan padanya. offsetWidth akan mencakup lebar batas, bantalan horizontal, lebar scrollbar vertikal, dll.

Bryan Friedman
sumber
Itulah yang membuat solusi teratas, tetapi karena teks Anda dapat dibagi menjadi beberapa baris, mereka menambahkan beberapa gaya CSS ke teks untuk mendapatkan lebar teks penuh yang sebenarnya.
Adrian Maire
2

Kode-snips di bawah ini, "menghitung" lebar span-tag, menambahkan "..." padanya jika terlalu panjang dan mengurangi panjang teks, sampai pas dengan induknya (atau sampai ia mencoba lebih dari seribu kali)

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 (dengan 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)
        }
    }
});
Techek
sumber
2
Coba pencarian biner alih-alih mengulang satu karakter sekaligus: lihat komentar saya pada jawaban Alex untuk stackoverflow.com/questions/536814/…
StanleyH
@ StanleyH: Ide bagus - Saya akan menerapkan saran Anda sesegera mungkin.
Techek
2

Yang lebih baik adalah mendeteksi apakah teks akan pas sebelum Anda menampilkan elemen. Jadi Anda dapat menggunakan fungsi ini yang tidak memerlukan elemen berada di layar.

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;
}

Pemakaian:

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

Jika ada orang lain yang datang ke sini mencari cara untuk mengukur lebar string dan cara untuk mengetahui apa ukuran font terbesar yang sesuai dengan lebar tertentu, berikut adalah fungsi yang dibangun di atas solusi @ Domi dengan pencarian biner :

/**
 * 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;
        }
    }
}
M Katz
sumber
Ini berfungsi luar biasa (ditambah dengan kode dari jawaban Domi)
r3wt
1

Coba kode ini:

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;
}
Jason Bracey
sumber
1

Lebar dan tinggi teks dapat diperoleh dengan clientWidthdanclientHeight

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

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

pastikan properti posisi style diatur ke absolut

element.style.position = "absolute";

tidak wajib berada di dalam div, bisa di dalam patauspan

Gjaa
sumber
1

Membangun dari jawaban Deepak Nadar , saya mengubah parameter fungsi untuk menerima gaya teks dan font. Anda tidak perlu merujuk elemen. Juga, fontOptionsmemiliki default, sehingga Anda tidak perlu menyediakan semuanya.

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

Pak Polywhirl
sumber
0

Saya kira ini hampir mirip dengan entri Depak, tetapi didasarkan pada karya Louis Lazaris yang diterbitkan pada sebuah artikel di halaman impressivewebs

(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);

Acara fit digunakan untuk menjalankan pemanggilan fungsi secara langsung setelah fungsi dikaitkan dengan kontrol.

misal: $ ('input'). autofit (). trigger ("fit");

Mauricio
sumber
0

Tanpa 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);
v1r00z
sumber
ketika Anda mengatur angka tidak berfungsi, karena tidak ada ruang yang diperlukan, jika Anda menghapusnya, itu akan berfungsi dengan baik: fontSize + "px arial" -> fontSize + "px arial", hanya itu.
Alberto Acuña
0

Contoh biola yang bekerja: 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>

Kode 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");
Jason Williams
sumber
0

The Element.getClientRects()metode mengembalikan koleksi DOMRectbenda-benda yang menunjukkan persegi panjang berlari untuk setiap kotak perbatasan CSS di klien. Nilai yang dikembalikan adalah kumpulan DOMRectobjek, satu untuk setiap kotak batas CSS yang terkait dengan elemen. Setiap DOMRectobjek berisi read-only left, top, rightdan bottomsifat-sifat yang menggambarkan kotak perbatasan, dalam pixel, dengan relatif kiri atas ke kiri atas viewport.

Element.getClientRects () oleh Mozilla Contributors dilisensikan di bawah CC-BY-SA 2.5 .

Menjumlahkan semua lebar persegi panjang yang dikembalikan menghasilkan lebar teks total dalam piksel.

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>

transistor09
sumber
0

Saya telah membuat modul ES6 kecil (menggunakan 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();
}

Mudah digunakan:

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

Hal keren yang mungkin Anda perhatikan - memungkinkan untuk memperhitungkan semua atribut CSS, bahkan paddings!

Roman86
sumber
0

Anda juga dapat melakukan ini dengan createRange, yang lebih akurat, daripada teknik kloning teks:

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;
}
Termasuk33
sumber
-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'));
kavun
sumber