คำนวณความกว้างของข้อความด้วย JavaScript


467

ฉันต้องการใช้ JavaScript เพื่อคำนวณความกว้างของสตริง เป็นไปได้โดยไม่ต้องใช้แบบอักษร monospace หรือไม่

ถ้าไม่ใช่ในตัวความคิดเดียวของฉันคือการสร้างตารางความกว้างสำหรับตัวละครแต่ละตัว แต่นี่มันไม่มีเหตุผลมากนักโดยเฉพาะอย่างยิ่งการสนับสนุนUnicodeและขนาดของประเภทที่แตกต่างกัน (และเบราว์เซอร์ทั้งหมดสำหรับเรื่องนั้น)


10
ระวังว่าหากคุณใช้แบบอักษรภายนอกคุณจะต้องใช้เทคนิคด้านล่างหลังจากที่พวกเขาได้โหลดแล้ว คุณอาจไม่ตระหนักถึงสิ่งนี้หากคุณมีแคชหรือมีการติดตั้งเวอร์ชันในเครื่อง
Seth W. Klein

คำตอบ:


355

สร้างสไตล์ DIV ด้วยสไตล์ดังต่อไปนี้ ใน JavaScript ของคุณตั้งค่าขนาดตัวอักษรและคุณลักษณะที่คุณพยายามวัดใส่สตริงของคุณใน DIV จากนั้นอ่านความกว้างและความสูงปัจจุบันของ DIV มันจะยืดให้พอดีกับเนื้อหาและขนาดจะอยู่ในพิกเซลไม่กี่พิกเซลของขนาดที่แสดงผล

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
สิ่งเดียวที่ฉันเพิ่มคือมันอาจให้มิติที่ไม่ถูกต้องตามสไตล์ที่ใช้ โปรดจำไว้ว่าคุณอาจมีรูปแบบเช่น p {ระยะห่างระหว่างตัวอักษร: 0.1em; } ว่าองค์ประกอบ DIV จะไม่สะท้อน คุณต้องให้แน่ใจว่าสไตล์ที่เหมาะสมกับที่ที่คุณจะใช้ข้อความ
Jim

5
ความคิดเห็นของ Ditto Jim - ตรวจสอบอีกครั้งเพื่อให้แน่ใจว่าคอนเทนเนอร์ในกรณีนี้ไม่มีลักษณะอื่นใดที่ใช้กับมันผ่านกฎการเลือก css ที่คุณอาจไม่คุ้นเคยในเวลานั้น ตัดรูปแบบที่เกี่ยวข้องทั้งหมดออกจากตู้คอนเทนเนอร์ก่อนใช้สิ่งที่คุณสนใจก่อนทำการวัด
35432 Jason

44
คุณควรใส่ใน white-space: nowrap ถ้าคุณคิดว่าข้อความจะเกินความกว้างของเบราว์เซอร์
สมุนไพร Caudill

5
@ BBog ทั้งหมดที่แฮ็คไปรอบ ๆ คือเหตุผลที่ฉันแนะนำแฮ็คที่ต่างออกไปให้น้อยลงเข้าหาชั้นล่าง ลองดูที่มันนี่
Domi

11
แค่อยากรู้ว่า+1มันมีไว้สำหรับอะไรในแต่ละมิติ?
คิป

385

ในHTML 5คุณสามารถใช้วิธี Canvas.measureText (คำอธิบายเพิ่มเติมที่นี่ )

ลองเล่นซอนี้ดูสิ :

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

ซอนี้นี้เปรียบเทียบวิธี Canvas นี้กับรูปแบบวิธีDOMของBob Monteverdeเพื่อให้คุณสามารถวิเคราะห์และเปรียบเทียบความแม่นยำของผลลัพธ์

มีข้อดีหลายประการสำหรับวิธีนี้ ได้แก่ :

หมายเหตุ: เมื่อคุณเพิ่มข้อความใน DOM ของคุณอย่าลืมคำนึงถึงช่องว่างภายในขอบและขอบด้วย

หมายเหตุ 2: ในเบราว์เซอร์บางวิธีวิธีนี้ให้ความแม่นยำพิกเซลย่อย (ผลลัพธ์คือหมายเลขจุดลอย), อื่น ๆ มันไม่ได้ (ผลเป็นเพียง int) คุณอาจต้องการเรียกใช้Math.floor(หรือMath.ceil) กับผลลัพธ์เพื่อหลีกเลี่ยงความไม่สอดคล้องกัน เนื่องจากวิธีการอิงจาก DOM นั้นไม่เคยแม่นยำพิกเซลย่อยวิธีนี้จึงมีความแม่นยำสูงกว่าวิธีอื่น ๆ ที่นี่

ตามjsperf นี้ (ขอบคุณผู้มีส่วนร่วมในความคิดเห็น) วิธีการ Canvasและวิธีการใช้DOMนั้นเร็วพอ ๆ กันหากการแคชถูกเพิ่มในวิธีการใช้ DOMและคุณไม่ได้ใช้ Firefox ใน Firefox ด้วยเหตุผลบางอย่างวิธี Canvasนี้เร็วกว่าวิธีแบบอิง DOM มาก (จนถึงเดือนกันยายน 2014)


7
นี่เป็นตัวเลือกที่ยอดเยี่ยมฉันไม่รู้เกี่ยวกับมัน เคยเปรียบเทียบประสิทธิภาพของสิ่งนี้กับประสิทธิภาพของการวัดใน DOM หรือไม่
SimplGy

2
ฉันเพิ่มแคชไปที่มาตรฐาน jsperf ตอนนี้ทั้งสองวิธีมีความคล้ายคลึง
Brandon Bloom

1
@ มาร์ตินห๊ะ? "องค์ประกอบ HTML มากมาย" เกี่ยวข้องกับอะไรที่นี่บ้าง วัตถุ Canvas ในตัวอย่างนี้ไม่ได้แนบกับ DOM และแม้กระทั่งนอกเหนือจากที่มีการเปลี่ยนแปลงตัวอักษรในบริบทของการวาดภาพบนผืนผ้าใบไม่ได้ส่งผลกระทบต่อผืนผ้าใบที่ทุกจนกว่าคุณหรือstrokeText() fillText()บางทีคุณอาจต้องการแสดงความคิดเห็นในคำตอบที่ต่างออกไป?
Ajedi32

1
ทางออกที่ดี ฉันได้ห่อวิธีอื่นสองสามรอบคำตอบของ Domi เพื่อที่ฉันจะได้รับ (อาจ) สตริงที่ถูกตัดทอนด้วยจุดไข่ปลา (... ) ในตอนท้ายถ้ามันจะไม่พอดีในพื้นที่ที่กำหนด (เท่าของสตริง จะถูกนำมาใช้) - ผ่านในองค์ประกอบ JQuery ที่จะมีสตริง (อาจถูกตัดทอน) และกำหนดแอตทริบิวต์ของตัวอักษรแบบไดนามิกเพื่อให้พวกเขาไม่จำเป็นต้องเขียนโค้ดแบบยากปล่อยให้แอตทริบิวต์ CSS แบบอักษรเปลี่ยนโดยไม่ทำลาย เค้าโครง JSFiddle ที่นี่: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey

2
ดีเพราะผู้ใช้มองไม่เห็น!
clabe45

110

นี่คือสิ่งที่ฉันวิปปิ้งด้วยกันโดยไม่มีตัวอย่าง ดูเหมือนว่าเราทุกคนอยู่ในหน้าเดียวกัน

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

ใช้ง่ายมาก: "a string".width()

** เพิ่มwhite-space: nowrapดังนั้นสตริงที่มีความกว้างใหญ่กว่าความกว้างหน้าต่างสามารถคำนวณได้


2
ขอบคุณ JordanC สิ่งหนึ่งที่ฉันจะเพิ่มคือถ้าคุณกำลังเรียกสิ่งนี้หลายครั้งในหน้าเดียวกันและประสิทธิภาพเป็นปัญหาคุณสามารถยืนยัน DIV ได้และเพียงแค่เปลี่ยนเนื้อหาและตรวจสอบความกว้าง ฉันเพิ่งทำแบบนี้เมื่อทุกอย่างถูกพูดและทำแล้ว DOM ก็จะเหมือนกับเมื่อคุณเริ่มต้น
Bob Monteverde

3
ฉันจะไม่เพิ่มวิธีนี้Stringเนื่องจากจะทำให้การแยกข้อกังวลของโปรแกรมของคุณลดลง(รหัสหลักแยกกับรหัส UI) ลองนึกภาพคุณต้องการที่จะพอร์ตรหัสหลักของคุณไปยังแพลตฟอร์มที่มีกรอบ UI ที่แตกต่างกันมาก ...
Domi

23
นี่เป็นการออกแบบที่ไม่ดีไม่เพียง แต่จะจับคู่โมเดลของคุณกับมุมมองของคุณ แต่ยังจับคู่มันกับ jQuery โดยตรง ยิ่งไปกว่านั้นนี่คือ reflow นรกนี่จะไม่ขยายขนาดได้อย่างแน่นอน
James

1
หากคุณต้องการค่าทศนิยมคุณสามารถใช้o[0].getBoundingClientRect().widthตามที่แนะนำที่นี่: stackoverflow.com/a/16072668/936397
Alexander Olsson

1
@virus พูดได้ดีว่ามีคนมากกว่า 100 คนที่ไม่สนใจประสิทธิภาพการทำงานเช่นกัน ... อย่างไรก็ตามก็ไม่ได้ทำให้สิ่งที่ฉันพูดถูกต้องหรือเป็นจริง
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

มันเหมาะกับฉัน ...

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

สวัสดีคำตอบของคุณเป็นจริงที่เป็นประโยชน์ แต่ใช้ .cssText แทน .style เพื่อสนับสนุน IE 8 และลด ..
ดิลลิป Rajkumar

คำตอบนี้ยอดเยี่ยม แต่เมื่อฉันสร้างข้อความขนาดใหญ่มันจะกลายเป็นพิกเซลที่ไม่ถูกต้อง เป็นเพราะความกว้างไม่ใช่จำนวนเต็มหรือไม่
Bobtroopo

20

ห้องสมุด ExtJS จาวาสคริปต์มีชั้นดีที่เรียกว่า Ext.util.TextMetrics ว่า "ให้การวัดที่แม่นยำพิกเซลสำหรับบล็อกของข้อความเพื่อให้คุณสามารถตรวจสอบว่าวิธีสูงและกว้างพิกเซลบล็อกที่ให้ข้อความที่จะเป็น" คุณสามารถใช้งานได้โดยตรงหรือดูซอร์สโค้ดของโค้ดเพื่อดูวิธีการทำงาน

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


1
ExtJS มีใบอนุญาตแปลก ๆ ไม่ว่าคุณจะจ่ายผู้ดูแลปัจจุบัน บริษัท Sencha ให้ใช้หรือคุณต้องเปิดซอร์สโค้ดที่เกี่ยวข้องทั้งหมดในใบสมัครของคุณ นี่คือตัวหยุดการแสดงสำหรับ บริษัท ส่วนใหญ่ ในทางกลับกัน jQuery ใช้ใบอนุญาต MIT ที่ได้รับอนุญาตอย่างสูง
devdanke

1
javascript ไม่ตรงตามข้อกำหนดของโอเพนซอร์สโดยอัตโนมัติหรือไม่ คุณให้บริการแหล่งที่มากับทุกคนที่ดูหน้า
PatrickO

10
มีความแตกต่างระหว่างความสามารถในการดูซอร์สโค้ดและโอเพ่นซอร์สซึ่งถูกกำหนดโดยการออกใบอนุญาต
Parker Ault

ขอบคุณจากพวกเราที่ยังใช้ ExtJS :-)
Monarch Wadia

1
คุณควรปล่อยให้ ExtJS พักอย่างสงบ
canbax

19

ฉันชอบ "ความคิดเพียงอย่างเดียว" ของคุณในการทำแผนที่ความกว้างตัวอักษรแบบคงที่! มันใช้งานได้ดีสำหรับวัตถุประสงค์ของฉัน บางครั้งด้วยเหตุผลด้านประสิทธิภาพหรือเนื่องจากคุณไม่สามารถเข้าถึง DOM ได้อย่างง่ายดายคุณอาจต้องการให้เครื่องคิดเลขแบบสแตนด์อโลนแบบแฮ็กที่รวดเร็วปรับเทียบเป็นแบบอักษรเดียว ดังนั้นนี่คือหนึ่งปรับเทียบกับ Helvetica; ผ่านสตริงและ (เป็นทางเลือก) ขนาดตัวอักษร:

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
}

อาร์เรย์ยักษ์ที่น่าเกลียดนั้นคือความกว้างอักขระ ASCII ที่จัดทำดัชนีโดยรหัสอักขระ ดังนั้นนี่สนับสนุน ASCII (ไม่เช่นนั้นจะถือว่าความกว้างอักขระเฉลี่ย) โชคดีที่ความกว้างนั้นปรับขนาดตัวอักษรแบบเชิงเส้นดังนั้นจึงใช้งานได้กับตัวอักษรทุกขนาด มันเห็นได้ชัดว่าขาดการรับรู้ถึงการจัดช่องไฟหรือหนังสติ๊กหรืออะไรก็ตาม

ในการ "ปรับเทียบ" ฉันเพิ่งแสดงอักขระทุกตัวถึง charCode 126 (ตัวหนอนอันยิ่งใหญ่) ใน svg และได้รับกล่องขอบเขตและบันทึกลงในอาร์เรย์นี้ รหัสเพิ่มเติมและคำอธิบายและสาธิตที่นี่


1
นั่นเป็นโซลูชันที่ชาญฉลาดหนึ่งอันดี :) ฉันมักจะใช้แบบอักษร / ขนาดเดียวกันอยู่เสมอดังนั้นมันจึงเหมาะกับฉันดี ฉันพบว่าประสิทธิภาพของการแก้ปัญหา DOM / Canvas เป็นปัญหาจริงนี่เป็นเรื่องที่สะอาดจริงๆไชโย!
mikeapr4

1
ลบความต้องการผ้าใบ +1
frage

คุณสามารถกำจัด* fontSizeและใช้ 'em' ได้
Matt Fletcher

ช่างเป็นคำตอบที่ยอดเยี่ยมมาก!
almosnow

11

ฉันเขียนเครื่องมือเล็กน้อยสำหรับสิ่งนั้น อาจเป็นประโยชน์กับบางคน มันทำงานได้โดยไม่ต้อง jQuery

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

การใช้งาน:

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

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

ซอ: http://jsfiddle.net/PEvL8/


7

คุณสามารถใช้ Canvas เพื่อไม่ให้คุณจัดการกับคุณสมบัติ 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;

นั่นไม่ใช่เฮฟวี่เวทมากขึ้น (ด้วยการรับบริบท 2d ฯลฯ ) มากกว่าการสร้างองค์ประกอบ DOM และระบุคุณสมบัติ CSS สำหรับมันหรือไม่
Pharao2k

1
นี่เป็นวิธีการที่สะอาดหากคุณใช้ Canvas สำหรับบางสิ่งอยู่แล้ว แต่ช้ามาก การเรียกใช้ข้อความการวัดเพียงอย่างเดียวใช้เวลาประมาณ 8-10 ms (โดยใช้ Chrome)
Rui Marques

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

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

สิ่งนี้จะทำงานได้ตราบใดที่แท็ก <span> ไม่มีสไตล์อื่นที่ใช้กับมัน offsetWidth จะรวมความกว้างของเส้นขอบใด ๆ การขยายแนวนอนความกว้างของแถบเลื่อนแนวตั้ง ฯลฯ


นั่นคือสิ่งที่สร้างโซลูชันบนหรือมากกว่า แต่เนื่องจากข้อความของคุณอาจแบ่งออกเป็นหลายบรรทัดพวกเขาเพิ่มสไตล์ CSS บางอย่างลงในข้อความเพื่อให้ได้ความกว้างของข้อความเต็มที่แท้จริง
Adrian Maire

2

โค้ด - สนิปด้านล่าง "คำนวณ" ความกว้างของสแปน - แท็กต่อท้าย "... " หากมันยาวเกินไปและลดความยาวของข้อความจนกว่าจะพอดีกับพาเรนต์ (หรือจนกว่าจะลองมากกว่า หนึ่งพันครั้ง)

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 (พร้อม 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
ลองค้นหาแบบไบนารี่แทนการวนลูป 1 ตัวในแต่ละครั้ง: ดูความคิดเห็นของฉันเกี่ยวกับคำตอบของ Alex ที่stackoverflow.com/questions/536814/…
StanleyH

@ StanleyH: ความคิดที่ดี - ฉันจะใช้ข้อเสนอแนะของคุณโดยเร็วที่สุด
Techek

2

ที่ดีกว่าคือการตรวจสอบว่าข้อความจะพอดีก่อนที่คุณจะแสดงองค์ประกอบ ดังนั้นคุณสามารถใช้ฟังก์ชั่นนี้ซึ่งไม่ต้องการองค์ประกอบที่จะอยู่บนหน้าจอ

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

การใช้งาน:

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

2

ในกรณีที่คนอื่นมาที่นี่เพื่อหาวิธีวัดความกว้างของสตริงและวิธีรู้ขนาดตัวอักษรที่ใหญ่ที่สุดที่จะพอดีกับความกว้างเฉพาะนี่คือฟังก์ชันที่สร้างขึ้นบนโซลูชันของ @ Domi ด้วยการค้นหาแบบไบนารี :

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

มันใช้งานได้อย่างน่าอัศจรรย์ (ควบคู่กับโค้ดจากคำตอบของ Domi)
r3wt

1

ลองรหัสนี้:

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

ความกว้างและความสูงของข้อความสามารถรับได้ด้วยclientWidthและclientHeight

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

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

ตรวจสอบให้แน่ใจว่าคุณสมบัติตำแหน่งสไตล์ถูกตั้งค่าเป็นสัมบูรณ์

element.style.position = "absolute";

ไม่จำเป็นต้องอยู่ภายใน a divสามารถอยู่ภายในpหรือได้span


1

นอกเหนือจากคำตอบของDeepak Nadarฉันเปลี่ยนพารามิเตอร์ฟังก์ชั่นเพื่อยอมรับข้อความและรูปแบบตัวอักษร คุณไม่จำเป็นต้องอ้างอิงองค์ประกอบ นอกจากนี้ยังfontOptionsมีค่าเริ่มต้นดังนั้นคุณไม่จำเป็นต้องจัดหาสิ่งเหล่านั้นทั้งหมด

(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

ฉันเดาว่านี่ prety คล้ายกับรายการ Depak แต่ขึ้นอยู่กับงานของ Louis Lazaris เผยแพร่ที่บทความในหน้าเว็บที่น่าประทับใจ

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

เหตุการณ์พอดีจะใช้ในการดำเนินการเรียกใช้ฟังก์ชั่นในทันทีหลังจากที่ฟังก์ชั่นจะเกี่ยวข้องกับการควบคุม

เช่น: $ ('input'). autofit (). trigger ("fit");


0

ไม่มี 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);

เมื่อคุณตั้งค่าหมายเลขใช้งานไม่ได้เนื่องจากไม่มีช่องว่างที่จำเป็นหากคุณลบออกมันจะทำงานได้ดี: fontSize + "px arial" -> fontSize + "px arial" เพียงแค่นั้น
Alberto Acuña

0

ซอตัวอย่างการทำงาน: 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>

รหัส 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

Element.getClientRects()วิธีการส่งกลับคอลเลกชันของDOMRectวัตถุที่ระบุสี่เหลี่ยม bounding สำหรับแต่ละกล่องชายแดน CSS ในลูกค้า ค่าที่ส่งคืนคือชุดของDOMRectวัตถุหนึ่งรายการสำหรับแต่ละกล่องขอบ CSS ที่เกี่ยวข้องกับองค์ประกอบ แต่ละDOMRectวัตถุมีอ่านอย่างเดียวleft, top, rightและbottomคุณสมบัติอธิบายกล่องชายแดนพิกเซลกับญาติบนด้านซ้ายไปด้านบนซ้ายของวิวพอร์ต

Element.getClientRects ()โดยMozilla ร่วมให้อยู่ภายใต้สัญญาCC-BY-SA 2.5

การรวมความกว้างของสี่เหลี่ยมผืนผ้าที่ส่งคืนทั้งหมดให้ความกว้างของข้อความทั้งหมดเป็นพิกเซล

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

ฉันได้สร้างโมดูล ES6 เล็ก ๆ (ใช้ 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();
}

ง่ายต่อการใช้:

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

สิ่งที่ยอดเยี่ยมที่คุณอาจสังเกตเห็น - มันช่วยให้คำนึงถึงคุณสมบัติ CSS ใด ๆ แม้จะมีช่องว่างภายใน!


0

คุณสามารถทำได้ด้วย createRange ซึ่งแม่นยำกว่าเทคนิคการโคลนข้อความ:

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'));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.