[javascript] SVG는 텍스트 요소 너비를 얻습니다.

나는 SVG 파일을 일부 ECMAScript를 / 자바 스크립트 작업을하고 얻을 필요가있어 widthheighttext내가 그것을 둘러싸는 사각형의 크기를 조절할 수 있도록 요소입니다. HTML에서는 요소 의 offsetWidthoffsetHeight속성 을 사용할 수 있지만 해당 속성을 사용할 수없는 것으로 보입니다.

작업해야 할 부분이 있습니다. 텍스트를 변경할 때마다 사각형의 너비를 변경해야하는데 요소 의 실제 width(픽셀) 를 얻는 방법을 모르겠습니다 text.

<rect x="100" y="100" width="100" height="100" />
<text>Some Text</text>

어떤 아이디어?



답변

var bbox = textElement.getBBox();
var width = bbox.width;
var height = bbox.height;

그런 다음 그에 따라 rect의 속성을 설정하십시오.

링크 : getBBox()SVG v1.1 표준에서.


답변

텍스트 길이와 관련하여 링크는 BBox와 getComputedTextLength ()가 약간 다른 값을 반환 할 수 있지만 서로 상당히 가까운 값을 반환 할 수 있습니다.

http://bl.ocks.org/MSCAU/58bba77cdcae42fc2f44


답변

document.getElementById('yourTextId').getComputedTextLength();

나를 위해 일했다


답변

호환성을 위해 다음과 같이 어떻습니까?

function svgElemWidth(elem) {
    var methods = [ // name of function and how to process its result
        { fn: 'getBBox', w: function(x) { return x.width; }, },
        { fn: 'getBoundingClientRect', w: function(x) { return x.width; }, },
        { fn: 'getComputedTextLength', w: function(x) { return x; }, }, // text elements only
    ];
    var widths = [];
    var width, i, method;
    for (i = 0; i < methods.length; i++) {
        method = methods[i];
        if (typeof elem[method.fn] === 'function') {
            width = method.w(elem[method.fn]());
            if (width !== 0) {
                widths.push(width);
            }
        }
    }
    var result;
    if (widths.length) {
        result = 0;
        for (i = 0; i < widths.length; i++) {
            result += widths[i];
        }
        result /= widths.length;
    }
    return result;
}

이것은 세 가지 방법의 유효한 결과의 평균을 반환합니다. 이상 값을 제거하거나 getComputedTextLength요소가 텍스트 요소 인 경우 선호하도록 개선 할 수 있습니다.

경고 : 주석에서 말했듯 getBoundingClientRect이은 까다 롭습니다. 메서드에서 제거하거나 getBoundingClientRect좋은 결과를 반환 하는 요소에만 이것을 사용 하므로 회전이없고 크기 조정이 없을 것입니다 (?)


답변

이유는 확실하지 않지만 위의 방법 중 어느 것도 나를 위해 작동하지 않습니다. 캔버스 방식으로 어느 정도 성공했지만 모든 종류의 스케일 팩터를 적용해야했습니다. 스케일 팩터에도 불구하고 Safari, Chrome 및 Firefox간에 일관성없는 결과가있었습니다.

그래서 다음을 시도했습니다.

            var div = document.createElement('div');
            div.style.position = 'absolute';
            div.style.visibility = 'hidden';
            div.style.height = 'auto';
            div.style.width = 'auto';
            div.style.whiteSpace = 'nowrap';
            div.style.fontFamily = 'YOUR_FONT_GOES_HERE';
            div.style.fontSize = '100';
            div.style.border = "1px solid blue"; // for convenience when visible

            div.innerHTML = "YOUR STRING";
            document.body.appendChild(div);

            var offsetWidth = div.offsetWidth;
            var clientWidth = div.clientWidth;

            document.body.removeChild(div);

            return clientWidth;

훌륭하고 매우 정확했지만 Firefox에서만 작동했습니다. 크롬과 사파리를 구하기 위해 요소를 확장하지만 기쁨은 없습니다. Safari 및 Chrome 오류는 문자열 길이 또는 글꼴 크기와 선형 적이 지 않습니다.

그래서 두 번째로 접근하십시오. 나는 무차별 대입 접근 방식을별로 신경 쓰지 않지만 몇 년 동안 이것을 켜고 끄는 데 어려움을 겪은 후 시도해보기로 결정했습니다. 인쇄 가능한 각 개별 문자에 대해 상수 값을 생성하기로 결정했습니다. 일반적으로 이것은 다소 지루하지만 다행히도 Firefox는 매우 정확합니다. 다음은 두 부분으로 구성된 무차별 대입 솔루션입니다.

<body>
        <script>

            var div = document.createElement('div');
            div.style.position = 'absolute';
            div.style.height = 'auto';
            div.style.width = 'auto';
            div.style.whiteSpace = 'nowrap';
            div.style.fontFamily = 'YOUR_FONT';
            div.style.fontSize = '100';          // large enough for good resolution
            div.style.border = "1px solid blue"; // for visible convenience

            var character = "";
            var string = "array = [";
            for(var i=0; i<127; i++) {
                character = String.fromCharCode(i);
                div.innerHTML = character;
                document.body.appendChild(div);

                var offsetWidth = div.offsetWidth;
                var clientWidth = div.clientWidth;
                console.log("ASCII: " + i + ", " + character + ", client width: " + div.clientWidth);

                string = string + div.clientWidth;
                if(i<126) {
                    string = string + ", ";
                }

                document.body.removeChild(div);

            }

            var space_string = "! !";
            div.innerHTML = space_string;
            document.body.appendChild(div);
            var space_string_width = div.clientWidth;
            document.body.removeChild(div);
            var no_space_string = "!!";
            div.innerHTML = no_space_string;
            document.body.appendChild(div);
            var no_space_string_width = div.clientWidth;
            console.log("space width: " + (space_string_width - no_space_string_width));
            document.body.removeChild(div);


            string = string + "]";
            div.innerHTML = string;
            document.body.appendChild(div);
            </script>
    </body>

참고 : 위 코드 조각은 정확한 값 배열을 생성하기 위해 Firefox에서 실행되어야합니다. 또한 배열 항목 32를 콘솔 로그의 공간 너비 값으로 바꿔야합니다.

Firefox 화면 텍스트를 복사하여 내 자바 스크립트 코드에 붙여 넣기 만하면됩니다. 이제 인쇄 가능한 문자 길이의 배열이 있으므로 get width 함수를 구현할 수 있습니다. 다음은 코드입니다.

const LCARS_CHAR_SIZE_ARRAY = [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, 17, 26, 46, 63, 42, 105, 45, 20, 25, 25, 47, 39, 21, 34, 26, 36, 36, 28, 36, 36, 36, 36, 36, 36, 36, 36, 27, 27, 36, 35, 36, 35, 65, 42, 43, 42, 44, 35, 34, 43, 46, 25, 39, 40, 31, 59, 47, 43, 41, 43, 44, 39, 28, 44, 43, 65, 37, 39, 34, 37, 42, 37, 50, 37, 32, 43, 43, 39, 43, 40, 30, 42, 45, 23, 25, 39, 23, 67, 45, 41, 43, 42, 30, 40, 28, 45, 33, 52, 33, 36, 31, 39, 26, 39, 55];


    static getTextWidth3(text, fontSize) {
        let width = 0;
        let scaleFactor = fontSize/100;

        for(let i=0; i<text.length; i++) {
            width = width + LCARS_CHAR_SIZE_ARRAY[text.charCodeAt(i)];
        }

        return width * scaleFactor;
    }

글쎄, 그게 다야. 무차별 대입이지만 세 가지 브라우저 모두에서 매우 정확하며 내 좌절 수준이 0으로 떨어졌습니다. 브라우저가 진화함에 따라 얼마나 오래 지속 될지 확실하지 않지만 SVG 텍스트에 대한 강력한 글꼴 메트릭 기술을 개발하기에 충분히 길어야합니다.


답변

SVG 사양에는이 정보를 반환하는 특정 방법이 있습니다. getComputedTextLength()

var width = textElement.getComputedTextLength(); // returns a pixel number


답변