2009-10-28 15 views
83

मैं एक एसवीजी फ़ाइल के लिए कुछ ECMAScript/जावास्क्रिप्ट पर काम कर रहा हूँ और width और एक text तत्व की height पाने के लिए तो मैं एक आयत है कि यह चारों ओर से घेरे आकार बदल सकते हैं की जरूरत है। एचटीएमएल में मैं तत्व पर offsetWidth और offsetHeight विशेषताओं का उपयोग करने में सक्षम हूं लेकिन ऐसा लगता है कि वे गुण अनुपलब्ध हैं।एसवीजी पाठ तत्व मिल चौड़ाई

यहां एक टुकड़ा है जिसके साथ मुझे काम करने की आवश्यकता है। जब भी मैं टेक्स्ट बदलता हूं, मुझे आयताकार की चौड़ाई बदलने की ज़रूरत है, लेकिन मुझे नहीं पता कि text तत्व के वास्तविक width (पिक्सल में) कैसे प्राप्त करें।

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

कोई विचार?

उत्तर

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

और उसके बाद रेक्ट के गुणों को तदनुसार सेट करें।

लिंक: getBBox() एसवीजी v1.1 मानक में।

+1

धन्यवाद मेरे लिए काम किया। मुझे एक और समारोह भी मिला जो चौड़ाई के साथ मदद कर सकता था। textElement.getComputedTextLength()। मैं आज रात दोनों कोशिश करूँगा और देखें कि मेरे लिए कौन सा बेहतर काम करता है। – spudly

+4

मैं इन पिछले सप्ताह के साथ खेल रहा था; GetComputedTextLength() विधि ने वही परिणाम लौटाया जो GetBBox()। चीजों के लिए चौड़ाई मैंने कोशिश की, इसलिए मैं बस बाउंडिंग बॉक्स के साथ गया, क्योंकि मुझे चौड़ाई और ऊंचाई दोनों की आवश्यकता थी। मुझे यकीन नहीं है कि क्या कोई परिस्थितियां हैं जब पाठ की लंबाई चौड़ाई से अलग होगी: मुझे लगता है कि शायद यह विधि टेक्स्ट लेआउट में मदद के लिए प्रदान की जाती है जैसे कि एकाधिक लाइनों पर टेक्स्ट को विभाजित करना, जबकि बाउंडिंग बॉक्स एक सामान्य विधि उपलब्ध है सभी (?) तत्वों पर। – NickFitz

+0

'getBBox()' का लिंक http://wiki.svg.org/index.php/GetBBox – RobM

5

टेक्स्ट की लंबाई के संबंध में लिंक बीबीओक्स को इंगित करता है और प्राप्त होता है कॉम्प्यूटेड टेक्स्टक्लेथेंथ() थोड़ा अलग मूल्य लौटा सकता है, लेकिन जो एक-दूसरे के काफी करीब हैं।

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

+0

उस लिंक के लिए धन्यवाद !! मुझे अपने आप से सभी परिदृश्यों में जाना पड़ा, लेकिन यह वास्तव में एक अच्छा सारांश है ... मेरी समस्या फ़ायरफ़ॉक्स पर एक त्सपैन तत्व पर getBBox() का उपयोग कर रही थी ... यह एक और अधिक विशिष्ट और परेशान करने वाला मुद्दा नहीं हो सकता .. । एक बार फिर धन्यवाद! –

2

कैसे संगतता के लिए कुछ इस तरह के बारे में:

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 अच्छे परिणाम वापस आ जाएगी पर इस का उपयोग, इसलिए कोई रोटेशन और शायद कोई स्केलिंग (?)

+0

getBoundingClientRect एक दूसरे के लिए एक संभावित रूप से भिन्न समन्वय प्रणाली में काम करता है। –

0

, सुनिश्चित नहीं क्यों, लेकिन उपरोक्त विधियों में से कोई भी मेरे लिए काम। मुझे कैनवास विधि के साथ कुछ सफलता मिली, लेकिन मुझे सभी प्रकार के पैमाने कारकों को लागू करना पड़ा। स्केल कारकों के साथ भी मुझे अभी भी सफारी, क्रोम और फ़ायरफ़ॉक्स के बीच असंगत परिणाम थे।

  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;

भयानक और सुपर सटीक है, लेकिन केवल फ़ायरफ़ॉक्स में काम किया:

तो, मैं निम्नलिखित की कोशिश की। क्रोम और सफारी के बचाव के लिए स्केल कारक, लेकिन कोई खुशी नहीं। यह पता चला है कि सफारी और क्रोम त्रुटियां या तो स्ट्रिंग लंबाई या फ़ॉन्ट आकार के साथ रैखिक नहीं हैं।

तो, नंबर दो से संपर्क करें। मुझे ब्रूट फोर्स दृष्टिकोण की बहुत परवाह नहीं है, लेकिन वर्षों से इस पर और बाद में संघर्ष करने के बाद मैंने इसे आज़माने का फैसला किया। मैंने प्रत्येक व्यक्तिगत प्रिंट करने योग्य चरित्र के लिए निरंतर मूल्य उत्पन्न करने का निर्णय लिया। आम तौर पर यह बहुत कठिन होगा, लेकिन सौभाग्य से फ़ायरफ़ॉक्स सुपर सटीक होता है।

<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); 
 
      console.log("space width: " + div.clientWidth - space_string.charCodeAt(0)*2); 
 
      document.body.removeChild(div); 
 

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

नोट:: यहाँ मेरी दो भाग जानवर बल समाधान है ऊपर टुकड़ा करने के लिए Firefox में मार डाला गया है मूल्यों का सही सरणी उत्पन्न करने के लिए। साथ ही, आपको कंसोल लॉग में स्पेस चौड़ाई मान के साथ सरणी आइटम 32 को प्रतिस्थापित करना होगा।

मैं बस फ़ायरफ़ॉक्स को स्क्रीन टेक्स्ट पर कॉपी करता हूं, और इसे अपने जावास्क्रिप्ट कोड में पेस्ट करता हूं। अब जब मेरे पास प्रिंट करने योग्य चरित्र लंबाई की सरणी है, तो मैं एक चौड़ाई कार्य लागू कर सकता हूं। कि यह है

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

ठीक है, यहाँ कोड है। ब्रूट फोर्स, लेकिन यह सभी तीन ब्राउज़रों में सुपर सटीक है, और मेरा निराशा स्तर शून्य हो गया है। यह सुनिश्चित नहीं है कि ब्राउज़रों के विकास के दौरान यह कितना समय टिकेगा, लेकिन मेरे एसवीजी पाठ के लिए एक मजबूत फ़ॉन्ट मेट्रिक्स तकनीक विकसित करने के लिए यह काफी लंबा होना चाहिए।

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

में

संबंधित मुद्दे