문제

JavaScript를 사용하여 문자열 너비를 계산하고 싶습니다.고정 폭 서체를 사용하지 않고도 이것이 가능합니까?

내장되어 있지 않은 경우 내 유일한 아이디어는 각 문자에 대한 너비 테이블을 만드는 것입니다. 그러나 이는 특히 지원하는 데 매우 불합리합니다. 유니코드 다양한 유형 크기(및 해당 문제에 대한 모든 브라우저).

도움이 되었습니까?

해결책

다음 스타일로 스타일이 지정된 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>

다른 팁

~ 안에 HTML5, 당신은 단지 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 https://stackoverflow.com/questions/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 메서드를 다음의 변형과 비교합니다. Bob Monteverde의 DOM 기반 방법, 결과의 정확성을 분석하고 비교할 수 있습니다.

이 접근 방식에는 다음과 같은 몇 가지 이점이 있습니다.

  • DOM과 같은 전역 상태를 변경하지 않기 때문에 다른 DOM 기반 방법보다 더 간결하고 안전합니다.
  • 추가 사용자 정의가 가능합니다. 추가 캔버스 텍스트 속성 수정, 와 같은 textAlign 그리고 textBaseline.

메모:DOM에 텍스트를 추가할 때 다음 사항도 고려해야 합니다. 패딩, 여백 및 테두리.

노트 2:일부 브라우저에서는 이 방법으로 하위 픽셀 정확도를 얻을 수 있지만(결과는 부동 소수점 숫자), 다른 브라우저에서는 그렇지 않습니다(결과는 정수만임).당신은 달리고 싶을 수도 있습니다 Math.floor (또는 Math.ceil) 결과에 따라 불일치를 방지합니다.DOM 기반 방법은 하위 픽셀 정확도가 아니기 때문에 이 방법은 여기의 다른 방법보다 훨씬 더 높은 정밀도를 갖습니다.

에 따르면 이 jsperf (댓글에 참여해주신 분들께 감사드립니다) 캔버스 방식 그리고 DOM 기반 방법 캐싱이 추가되면 거의 동일하게 빠릅니다. DOM 기반 방법 그리고 당신은 Firefox를 사용하고 있지 않습니다.Firefox에서는 어떤 이유로 이 캔버스 방식 것보다 훨씬 훨씬 빠릅니다. DOM 기반 방법 (2014년 9월 기준).

여기에 제가 예 없이 함께 채찍질한 것이 있습니다.우리 모두가 같은 페이지에 있는 것 같습니다.

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 따라서 창 너비보다 너비가 큰 문자열을 계산할 수 있습니다.

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

이것은 나에게 효과적입니다 ...

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

그만큼 ExtJS 자바스크립트 라이브러리 Ext.util.TextMetrics라는 훌륭한 클래스가 있습니다. 이 클래스는 "텍스트 블록에 대한 정확한 픽셀 측정값을 제공하여 주어진 텍스트 블록의 높이와 너비(픽셀 단위)를 정확하게 결정할 수 있습니다."이를 직접 사용하거나 소스에서 코드를 확인하여 이것이 어떻게 수행되는지 확인할 수 있습니다.

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

나는 그것을 위해 작은 도구를 썼습니다.아마도 누군가에게 유용할 것입니다.효과가있다 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/

나는 정적 문자 너비 맵을 수행하는 "유일한 아이디어"를 좋아합니다!실제로 내 목적에는 잘 작동합니다.때로는 성능상의 이유로 또는 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만 지원합니다(그렇지 않으면 평균 문자 너비를 가정합니다).다행스럽게도 너비는 기본적으로 글꼴 크기에 따라 선형적으로 확장되므로 모든 글꼴 크기에서 잘 작동합니다.커닝이나 합자 등에 대한 인식이 눈에 띄게 부족합니다.

"보정"을 위해 svg에서 charCode 126(강력한 물결표)까지의 모든 문자를 렌더링하고 경계 상자를 가져와 이 배열에 저장했습니다. 여기에 더 많은 코드와 설명 및 데모가 있습니다..

캔버스를 사용하면 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;
<span id="text">Text</span>

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

<span> 태그에 다른 스타일이 적용되어 있지 않은 한 이 방법은 작동합니다.offsetWidth에는 테두리 너비, 가로 패딩, 세로 스크롤 막대 너비 등이 포함됩니다.

아래 코드는 스팬 태그의 너비를 "계산"하고, 너무 길면 "..."를 추가하고 상위 요소에 맞을 때까지(또는 그 이상을 시도할 때까지 텍스트 길이를 줄입니다) 천 번)

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

다음 코드를 사용해 보세요:

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

텍스트의 너비와 높이는 다음을 사용하여 얻을 수 있습니다. clientWidth 그리고 clientHeight

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

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

스타일 위치 속성이 절대값으로 설정되어 있는지 확인하세요.

element.style.position = "absolute";

내부에 있을 필요는 없습니다. div, 내부에 있을 수 있습니다. p 또는 span

더 나은 방법은 요소를 표시하기 직전에 텍스트가 맞는지 여부를 감지하는 것입니다.따라서 요소가 화면에 표시될 필요가 없는 이 기능을 사용할 수 있습니다.

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) {
    ...
}

다음에서 구축 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>

다른 누군가가 문자열의 너비를 측정하는 방법을 찾고 있는 경우 그리고 특정 너비에 맞는 가장 큰 글꼴 크기가 무엇인지 확인하는 방법은 이진 검색을 통해 @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;
        }
    }
}

나는 이것이 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);

fit 이벤트는 함수가 컨트롤에 연결된 후 즉시 함수 호출을 실행하는 데 사용됩니다.

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

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

작업 예제의 바이올린: 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>

자바스크립트 코드:

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

그만큼 Element.getClientRects() 메소드는 컬렉션을 반환합니다. DOMRect 클라이언트의 각 CSS 테두리 상자에 대한 경계 사각형을 나타내는 개체입니다.반환된 값은 다음의 모음입니다. DOMRect 요소와 연결된 CSS 테두리 상자마다 하나씩.각 DOMRect 객체에 읽기 전용이 포함되어 있습니다. left, top, right 그리고 bottom 뷰포트의 왼쪽 위를 기준으로 왼쪽 위를 기준으로 테두리 상자를 픽셀 단위로 설명하는 속성입니다.

Element.getClientRects() ~에 의해 모질라 기여자 아래에 따라 라이선스가 부여됩니다. 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>

저는 작은 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 속성, 심지어 패딩까지 고려할 수 있다는 것입니다!

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'));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top