एसवीजी टेक्स्ट में ऑटो लाइन-रैपिंग


108

मैं <text>एसवीजी में एक प्रदर्शित करना चाहूंगा कि कंटेनर <rect>में ऑटो-लाइन-रैप क्या उसी तरह होगा जैसे HTML पाठ <div>तत्वों को भरता है। क्या इसे करने का कोई तरीका है? मैं <tspan>एस का उपयोग करके संयम से लाइनों को नहीं रखना चाहता ।

जवाबों:


89

पाठ रैपिंग SVG1.1 का हिस्सा नहीं है, वर्तमान में लागू कल्पना। आपको <foreignObject/>तत्व के माध्यम से HTML का उपयोग करना चाहिए ।

<svg ...>

<switch>
<foreignObject x="20" y="90" width="150" height="200">
<p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
</foreignObject>

<text x="20" y="20">Your SVG viewer cannot display html.</text>
</switch>

</svg>

5
यह स्विच का उपयोग करने का गलत तरीका है, इसे svg युक्ति में परिभाषित करतबों में से एक का उपयोग करने की आवश्यकता है। आपके उदाहरण में फ़ॉलबैक का उपयोग कभी नहीं किया जाएगा। W3.org/TR/SVG11/feature.html और w3.org/TR/SVG11/struct.html#SwitchElement देखें ।
एरिक डाहलस्ट्रम

22
इसके अलावा आईई में <ForeignObject /> का समर्थन नहीं किया गया है
डौग अमोस

3
लेकिन ध्यान रखें कि सभी इंजन विदेशी ऑबजेक्ट को रेंडर नहीं कर सकते हैं। विशेष रूप से, बैटिक नहीं करता है।
hrabinowitz

69

यहाँ एक विकल्प है:

<svg ...>
  <switch>
    <g requiredFeatures="http://www.w3.org/Graphics/SVG/feature/1.2/#TextFlow">
      <textArea width="200" height="auto">
       Text goes here
      </textArea>
    </g>
    <foreignObject width="200" height="200" 
     requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
      <p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
    </foreignObject>
    <text x="20" y="20">No automatic linewrapping.</text>
  </switch>
</svg>

यह देखते हुए कि भले ही फॉरेनऑबजेक्ट को उस करतबबाज़ी के साथ समर्थन के रूप में रिपोर्ट किया जा सकता है, इस बात की कोई गारंटी नहीं है कि HTML को प्रदर्शित किया जा सकता है क्योंकि एसवीजी 1.1 विनिर्देश द्वारा इसकी आवश्यकता नहीं है। फिलहाल html-in-Foreignobject सपोर्ट के लिए कोई करतब नहीं है। हालांकि, यह अभी भी कई ब्राउज़रों में समर्थित है, इसलिए भविष्य में इसकी आवश्यकता होने की संभावना है, शायद एक इसी करतब के साथ।

ध्यान दें कि SVG टिनी 1.2 में 'textArea' तत्व सभी मानक svg विशेषताओं, जैसे कि उन्नत फिलिंग आदि का समर्थन करता है, और यह कि आप ऑटो के रूप में चौड़ाई या ऊँचाई दोनों में से कोई भी निर्दिष्ट कर सकते हैं, जिसका अर्थ है कि पाठ उस दिशा में स्वतंत्र रूप से प्रवाह कर सकता है। फॉरेनऑबजेक्ट क्लिपिंग व्यूपोर्ट के रूप में कार्य करता है।

नोट: जबकि उपरोक्त उदाहरण एसवीजी 1.1 सामग्री मान्य है, एसवीजी 2 में 'आवश्यक फीचर्स' विशेषता को हटा दिया गया है, जिसका अर्थ है कि 'स्विच' तत्व एसवीजी 1.2 'टेक्स्टरी' के लिए समर्थन की परवाह किए बिना पहले 'जी' तत्व को प्रस्तुत करने का प्रयास करेगा। 'तत्व। SVG2 स्विच एलिमेंट स्पेक देखें ।


1
मैं एफएफ में इस कोड का परीक्षण कर रहा था, ब्राउज़र ने मुझे या तो टेक्स्टएयर तत्व या विदेशी ऑबजेक्ट बच्चे को नहीं दिखाया। तब कल्पना को पढ़ने के बाद, पाया गया कि आवश्यक सुविधाएँ विशेषता इस तरह से व्यवहार करती है कि, जब इसकी सूची झूठी हो जाती है, तो जिस तत्व में आवश्यक विशेषता होती है और उसके बच्चे संसाधित नहीं होते हैं। तो स्विच तत्व के लिए कोई आवश्यकता नहीं होगी। जब मैंने स्विच तत्व को हटा दिया, तब विदेशी ऑबजेक्ट बच्चे दिखाई दे रहे थे (क्योंकि मेरा ब्राउज़र (FF, 8.01) समर्थन svg1.1)। इसलिए मुझे लगता है कि यहां स्विच एलिमेंट की कोई जरूरत नहीं है। कृपया मुझे बताओ।
राजकमल सुब्रमण्यन

<G> तत्व का उपयोग करने के लिए अभी अपडेट किया गया है। एसवीजी कल्पना ने दर्शकों को अज्ञात तत्वों पर 'आवश्यक सुविधाएँ' देखने के लिए नहीं कहा था, इसलिए किसी को इसके लिए काम करने के लिए एक ज्ञात एसवीजी तत्व का उपयोग करना होगा।
एरिक डहलस्ट्रम

धन्यवाद! मुझे xhtml:divइसके बजाय उपयोग करने की आवश्यकता थी div, लेकिन यह d3.js. की वजह से हो सकता है मुझे TextFlow के बारे में कोई उपयोगी संदर्भ नहीं मिला, क्या यह (अभी भी) मौजूद है या यह केवल कुछ मसौदे में था?
जॉन्डोडो

2
यह ध्यान दिया जाना चाहिए कि textarea आगे बढ़ने के लिए समर्थित नहीं लगता है Bugzilla.mozilla.org/show_bug.cgi?id=413360
जॉर्ज मौयर

1
Chrome में उदाहरण काम नहीं करता है। अन्य ब्राउज़रों में परीक्षण नहीं किया है।
पॉज़फ़ान 12

15

पाठपाठ कुछ मामले के लिए अच्छा हो सकता है।

<svg width="200" height="200"
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <!-- define lines for text lies on -->
  <path id="path1" d="M10,30 H190 M10,60 H190 M10,90 H190 M10,120 H190"></path>
 </defs>
 <use xlink:href="#path1" x="0" y="35" stroke="blue" stroke-width="1" />
 <text transform="translate(0,35)" fill="red" font-size="20">
  <textPath xlink:href="#path1">This is a long long long text ......</textPath>
 </text>
</svg>

3
केवल उस मामले में जहां मध्य शब्द को लपेटना (और हाइफ़ेनटिंग नहीं) स्वीकार्य है। मैं कला परियोजनाओं से परे कई मामलों के बारे में नहीं सोच सकता, जहां यह ठीक है। http://jsfiddle.net/nilloc/vL3zj/
Nilloc

4
@ नीलोक हर कोई अंग्रेजी का उपयोग नहीं करता है, यह विधि चीनी, जापानी या कोरियाई के लिए पूरी तरह से ठीक है।
ज़ेंग मिंगजेई

@ZangMingJie वर्ण आधारित (तर्कपूर्ण) भाषाओं के लिए रैपिंग शब्दों को विभाजित करने की तुलना में एक बिल्कुल अलग उपयोग की तरह लगता है। जो सभी रोमांटिक / लैटिन / सिरिलिक / अरबी (ध्वन्यात्मक) भाषाओं में महत्वपूर्ण है, जो मेरी बात थी।
निलोक

11

@Mike Gledhill के कोड पर बिल्डिंग, मैंने इसे एक कदम आगे ले लिया है और अधिक मापदंडों को जोड़ा है। यदि आपके पास SVG RECT है और चाहते हैं कि पाठ इसके अंदर लपेटें, तो यह आसान हो सकता है:

function wraptorect(textnode, boxObject, padding, linePadding) {

    var x_pos = parseInt(boxObject.getAttribute('x')),
    y_pos = parseInt(boxObject.getAttribute('y')),
    boxwidth = parseInt(boxObject.getAttribute('width')),
    fz = parseInt(window.getComputedStyle(textnode)['font-size']);  // We use this to calculate dy for each TSPAN.

    var line_height = fz + linePadding;

// Clone the original text node to store and display the final wrapping text.

   var wrapping = textnode.cloneNode(false);        // False means any TSPANs in the textnode will be discarded
   wrapping.setAttributeNS(null, 'x', x_pos + padding);
   wrapping.setAttributeNS(null, 'y', y_pos + padding);

// Make a copy of this node and hide it to progressively draw, measure and calculate line breaks.

   var testing = wrapping.cloneNode(false);
   testing.setAttributeNS(null, 'visibility', 'hidden');  // Comment this out to debug

   var testingTSPAN = document.createElementNS(null, 'tspan');
   var testingTEXTNODE = document.createTextNode(textnode.textContent);
   testingTSPAN.appendChild(testingTEXTNODE);

   testing.appendChild(testingTSPAN);
   var tester = document.getElementsByTagName('svg')[0].appendChild(testing);

   var words = textnode.textContent.split(" ");
   var line = line2 = "";
   var linecounter = 0;
   var testwidth;

   for (var n = 0; n < words.length; n++) {

      line2 = line + words[n] + " ";
      testing.textContent = line2;
      testwidth = testing.getBBox().width;

      if ((testwidth + 2*padding) > boxwidth) {

        testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
        testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
        testingTSPAN.setAttributeNS(null, 'dy', line_height);

        testingTEXTNODE = document.createTextNode(line);
        testingTSPAN.appendChild(testingTEXTNODE);
        wrapping.appendChild(testingTSPAN);

        line = words[n] + " ";
        linecounter++;
      }
      else {
        line = line2;
      }
    }

    var testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
    testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
    testingTSPAN.setAttributeNS(null, 'dy', line_height);

    var testingTEXTNODE = document.createTextNode(line);
    testingTSPAN.appendChild(testingTEXTNODE);

    wrapping.appendChild(testingTSPAN);

    testing.parentNode.removeChild(testing);
    textnode.parentNode.replaceChild(wrapping,textnode);

    return linecounter;
}

document.getElementById('original').onmouseover = function () {

    var container = document.getElementById('destination');
    var numberoflines = wraptorect(this,container,20,1);
    console.log(numberoflines);  // In case you need it

};

धन्यवाद। क्रोम में पूरी तरह से काम करता है। लेकिन यह फ़ायरफ़ॉक्स में काम नहीं करता है। यह डेमो लिंक पर कहते हैं। अप्रत्याशित मान NaN पार्सिंग डाई विशेषता। svgtext_clean2.htm: 117 एक काम खोजने की कोशिश कर रहा है।
अक्षय तृतीया

मैंने बाद में इसे फ़ायरफ़ॉक्स में काम करना शुरू कर दिया। यहाँ आप जाएँ:
MSC

1
(अभी-अभी ENTER दबाया गया है।) मैंने बाद में इसे फ़ायरफ़ॉक्स और IE में काम किया। यदि आपको कुछ मदद चाहिए, तो democra.me/wrap_8_may_2014.htm पर एक नज़र डालें । कोड में फ़ायरफ़ॉक्स के बारे में एक टिप्पणी है।
एमएससी

जैसा कि आप देख सकते हैं, मैंने कोड को बाउंड बॉक्स को नीचे या नीचे सिकोड़ने या सही स्थान पर एक दीर्घवृत्त के साथ छोटा करने के लिए विस्तारित किया है।
एमएससी

मैं MSC के कोड में एक पंक्ति को संशोधित boxwidth = parseInt(boxObject.getAttribute('width'))करूंगा :, पिक्सेल में चौड़ाई boxwidth = parseInt(boxObject.getBBox().width)को स्वीकार करेगा , जबकि , किसी भी प्रकार की माप इकाई को स्वीकार करेगा
Massimiliano Caniparoli

9

यह कार्यक्षमता जावास्क्रिप्ट का उपयोग करके भी जोड़ा जा सकता है। Carto.net का एक उदाहरण है:

http://old.carto.net/papers/svg/textFlow/

कुछ और जो आपके लिए उपयोगी हो सकते हैं वे हैं आप संपादन योग्य पाठ क्षेत्र:

http://old.carto.net/papers/svg/gui/textbox/


४०४ - वे लिंक टूटे हुए हैं
मथायस

7

निम्नलिखित कोड ठीक काम कर रहा है। कोड स्निपेट चलाएं जो यह करता है।

शायद इसे साफ किया जा सकता है या यह स्वचालित रूप से एसवीजी में सभी पाठ टैग के साथ काम कर सकता है।

function svg_textMultiline() {

  var x = 0;
  var y = 20;
  var width = 360;
  var lineHeight = 10;
  
  

  /* get the text */
  var element = document.getElementById('test');
  var text = element.innerHTML;

  /* split the words into array */
  var words = text.split(' ');
  var line = '';

  /* Make a tspan for testing */
  element.innerHTML = '<tspan id="PROCESSING">busy</tspan >';

  for (var n = 0; n < words.length; n++) {
    var testLine = line + words[n] + ' ';
    var testElem = document.getElementById('PROCESSING');
    /*  Add line in testElement */
    testElem.innerHTML = testLine;
    /* Messure textElement */
    var metrics = testElem.getBoundingClientRect();
    testWidth = metrics.width;

    if (testWidth > width && n > 0) {
      element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
      line = words[n] + ' ';
    } else {
      line = testLine;
    }
  }
  
  element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
  document.getElementById("PROCESSING").remove();
  
}


svg_textMultiline();
body {
  font-family: arial;
  font-size: 20px;
}
svg {
  background: #dfdfdf;
  border:1px solid #aaa;
}
svg text {
  fill: blue;
  stroke: red;
  stroke-width: 0.3;
  stroke-linejoin: round;
  stroke-linecap: round;
}
<svg height="300" width="500" xmlns="http://www.w3.org/2000/svg" version="1.1">

  <text id="test" y="0">GIETEN - Het college van Aa en Hunze is in de fout gegaan met het weigeren van een zorgproject in het failliete hotel Braams in Gieten. Dat stelt de PvdA-fractie in een brief aan het college. De partij wil opheldering over de kwestie en heeft schriftelijke
    vragen ingediend. Verkeerde route De PvdA vindt dat de gemeenteraad eerst gepolst had moeten worden, voordat het college het plan afwees. "Volgens ons is de verkeerde route gekozen", zegt PvdA-raadslid Henk Santes.</text>

</svg>


1
एसवीजी टेक्स्ट में ऑटो लाइन-रैपिंग :) मेरा जावास्क्रिप्ट कोड तब लाइनें बनाता है जब टेक्स्ट लंबा होता है। यह अच्छा होगा यदि मैं एसवीजी के अंदर सभी टेक्स्ट टैग पर काम करता हूं। जावास्क्रिप्ट में आईडी = "" बदले बिना स्वचालित। एसवीजी को खराब करने के लिए बहु-रेखाएँ अपने आप होती हैं।
पीटर

अच्छा समाधान है, लेकिन आप इसे केंद्र में संरेखित कर सकते हैं?
क्रेसीमीर गालिक

उत्तर tbh स्वीकार किया जाना चाहिए। जावास्क्रिप्ट समाधान कम से कम पर्याप्त है और समझ में आता है।
Zac

4

मैंने एसवीजी "टेक्स्ट" तत्व में कुछ नकली शब्द-रैपिंग जोड़ने के लिए निम्नलिखित वाकथ्रू पोस्ट किया है:

एसवीजी वर्ड रैप - शो स्टॉपर?

आपको बस एक साधारण जावास्क्रिप्ट फ़ंक्शन जोड़ना होगा, जो आपके स्ट्रिंग को छोटे "tspan" तत्वों में विभाजित करता है। यहाँ एक उदाहरण है कि यह कैसा दिखता है:

उदाहरण एसवीजी

उम्मीद है की यह मदद करेगा !

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.