Frage

Ich bin auf einige ECMAScript/JavaScript-für eine SVG-Datei und müssen das width und height einer text element, so kann ich die Größe eines Rechtecks, das es umgibt.In HTML würde ich in der Lage sein zu verwenden offsetWidth und offsetHeight Attribute für das element, aber es scheint, dass diejenigen Eigenschaften nicht verfügbar sind.

Hier ist ein fragment, das ich brauche, mit zu arbeiten.Ich ändern müssen die Breite des Rechtecks, wenn ich den text ändern, aber ich weiß nicht, wie man die tatsächliche width (in Pixel) des text element.

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

Irgendwelche Ideen?

War es hilfreich?

Lösung

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

und dann legen Sie die rect-Eigenschaften entsprechend.

Link: getBBox() in der SVG-v1.1-standard.

Andere Tipps

In Bezug auf die Länge des Textes der link scheint zu zeigen BBox und getComputedTextLength() zurückgeben kann geringfügig unterschiedliche Werte, aber diejenigen, die sind ziemlich in der Nähe jedes andere.

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

Wie wäre es mit etwas wie diesem, um Kompatibilität:

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

Dies gibt den Durchschnitt von beliebigen gültigen Ergebnisse der drei Methoden.Sie könnten es verbessern zu vertreiben, Ausreißer oder zu Gunsten getComputedTextLength wenn das element ist ein text-element.

Warnung:Wie der Kommentar sagt, getBoundingClientRect ist schwierig.Entfernen Sie es von den Methoden oder der Benutzung dieser nur auf Elemente, wo getBoundingClientRect zurück gute Ergebnisse, so dass keine rotation und wohl auch keine Skalierung(?)

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

arbeitete für mich

Nicht sicher, warum, aber keines der oben genannten Methoden funktioniert für mich.Ich hatte einige Erfolge mit der canvas-Methode, aber ich hatte zu gelten alle Arten von Skala Faktoren.Auch mit der Skala Faktoren hatte ich noch inkonsistente Ergebnisse zwischen Safari, Chrome und Firefox.

So, ich habe versucht, die folgenden:

            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;

Gearbeitet genial und super präzise, aber nur in Firefox.Maßstab Faktoren ist die Rettung für Chrome und Safari, aber keine Freude.Stellt sich heraus, dass Safari und Chrome sind die Fehler nicht linear mit entweder string-Länge oder die Schriftgröße ändern.

So, Ansatz Nummer zwei.Ich weiß nicht viel Pflege für die brute-force-Ansatz, aber nach kämpfen mit diesem ein-und ausschalten für Jahre habe ich beschlossen, es zu versuchen.Ich beschloss, zu generieren Konstante Werte für die einzelnen druckbare Zeichen.Normalerweise wäre dies eine Art von langweilig, aber zum Glück Firefox geschieht, um super präzise.Hier ist meine zwei Teil brute-force-Lösung:

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

Hinweis:Das obige snippet ist ausgeführt in Firefox zu generieren eines genauen array von Werten.Auch, Sie nicht haben zu ersetzen Sie die array-Element 32 mit der Raum-Breite Wert in der Konsole anmelden.

Ich kopiere einfach den Firefox auf dem Bildschirm text, und fügen Sie es in meinen javascript-code.Jetzt, wo ich die array-von druckbaren Zeichen die Längen, die ich implementieren kann, eine get-Breite Funktion.Hier ist der code:

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

Gut, das ist es.Brute-force, aber es ist super präzise in allen drei Browsern, und meine frustration Ebene ist auf null zurückgegangen.Nicht sicher, wie lange es dauern wird, wie der Browser zu entwickeln, aber es sollte sein, lange genug für mich zu entwickeln, eine robuste font metrics Technik für meine SVG-text.

SVG-Spezifikation ist eine bestimmte Methode zum zurückgeben von dieser info: getComputedTextLength()

var width = textElement.getComputedTextLength(); // returns a pixel number
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top