जावास्क्रिप्ट के भीतर एक svg पाठ को कैसे प्रसारित करें?


107

तो यहाँ मेरे पास है:

<path class="..." onmousemove="show_tooltip(event,'very long text 
    \\\n I would like to linebreak')" onmouseout="hide_tooltip()" d="..."/>

<rect class="tooltip_bg" id="tooltip_bg" ... />
<text class="tooltip" id="tooltip" ...>Tooltip</text>

<script>
<![CDATA[
function show_tooltip(e,text) {
    var tt = document.getElementById('tooltip');
    var bg = document.getElementById('tooltip_bg');

    // set position ...

    tt.textContent=text;

    bg.setAttribute('width',tt.getBBox().width+10);
    bg.setAttribute('height',tt.getBBox().height+6);

    // set visibility ...
}
...

अब मेरे बहुत लंबे टूलटिप पाठ में एक लाइनब्रेक नहीं है, भले ही मैं चेतावनी का उपयोग करता हूं (); यह मुझे दिखाता है कि पाठ में वास्तव में दो लाइनें हैं। (इसमें एक "\" शामिल है, हालांकि, मैं उस एक को कैसे हटा सकता हूं?)
मुझे कहीं भी काम करने के लिए सीडीएटीए नहीं मिल सकता है।


2
किसी भी मौका इस svgjs.com/textflow अपने टूलटिप के साथ मदद कर सकता है?
एल्विन के।

@AlvinK। लिंक टूट गया है। मैंने नया स्थान खोजने का प्रयास किया, लेकिन असफल रहा।
गुत्थी 14

जवाबों:


150

यह कुछ ऐसा नहीं है जो एसवीजी 1.1 का समर्थन करता है। एसवीजी 1.2 में textAreaस्वचालित शब्द रैपिंग के साथ तत्व है, लेकिन यह सभी ब्राउज़रों में लागू नहीं है। एसवीजी 2 लागू करने की योजना नहीं हैtextArea , लेकिन इसमें ऑटो-लिपटे पाठ है

हालांकि, यह देखते हुए कि आप पहले से ही जानते हैं कि आपके लाइनब्रेक कहां होने चाहिए, आप अपने टेक्स्ट को कई <tspan>एस में, प्रत्येक के साथ x="0"और dy="1.4em"टेक्स्ट की वास्तविक लाइनों को अनुकरण करने के लिए तोड़ सकते हैं । उदाहरण के लिए:

<g transform="translate(123 456)"><!-- replace with your target upper left corner coordinates -->
  <text x="0" y="0">
    <tspan x="0" dy="1.2em">very long text</tspan>
    <tspan x="0" dy="1.2em">I would like to linebreak</tspan>
  </text>
</g>

बेशक, चूंकि आप जावास्क्रिप्ट से ऐसा करना चाहते हैं, इसलिए आपको DOM में प्रत्येक तत्व को मैन्युअल रूप से बनाना और सम्मिलित करना होगा।


2
और मैं कैसे पहचानूं कि कहां रखा जाए <tspan>s? बदलने के? विभाजित करें?
sollniss

2
कोशिश की कि यह var tspan = document.createElement('tspan') tspan.setAttribute('x','0'); tspan.setAttribute('dy','1.2em'); tspan.textContent = text; tt.appendChild(tspan); बिल्कुल भी कोई पाठ न दिखाए।
sollniss

2
क्या आप इस बात पर ध्यान देना चाहेंगे कि x = '0' डाई = '1.2em' की आवश्यकता क्यों है? यह काम करता है, वास्तव में, जैसा आपने कहा था। हालाँकि, मैं उन विशेषताओं के बिना भी काम करने की उम्मीद कर रहा था। इसके बजाय, कुछ भी प्रदर्शित नहीं किया गया है ... इसके अलावा, मैं इस बात पर पूरी तरह से स्पष्ट नहीं हूं कि आखिर लाइनब्रेक क्यों होता है। ऐसा नहीं है कि हमने कंटेनर की चौड़ाई को कुछ ठीक करने के लिए सेट किया है, ताकि यह लाइन ब्रेकिंग को लागू कर सके, क्या हमारे पास है?
कोनराड विल्टर्स्टन

4
x=0एक पूर्ण समन्वय है: पाठ टुकड़े को वर्तमान समन्वय प्रणाली के मूल में ले जाएं । transformपर विशेषता gतत्व को परिभाषित करता है एक नई वर्तमान समन्वय प्रणाली, और यह सोचते हैं कि पाठ है बाईं ओर संरेखित, tspan बाईं ओर ले जाया जाता है। यह कैरिज रिटर्न इंस्ट्रक्शन की तरह काम करता है। dy=1.2emएक सापेक्षिक समन्वय है: इस राशि द्वारा पाठ के टुकड़े को स्थानांतरित करें, वर्तमान पाठ टुकड़े के सापेक्ष। यह एक लाइन-फीड इंस्ट्रक्शन की तरह काम करता है। संयुक्त, आपको एक सीआर / एलएफ मिलता है।
सेर्गी डुमित्रिउ

अभी तक यह कोशिश नहीं की गई है: क्या आप समूह के बिना भी ऐसा कर सकते हैं? <text x = "100" y = "100"> <tspan x = "100" y = "100"> बहुत लंबा पाठ </ tspan> <tspan x = "100" y = "115"> मैं चाहूंगा लाइनब्रेक </ tspan> </ text> ??
रिचर्ड

25

मुझे लगता है कि आप इसे हल करने में कामयाब रहे, लेकिन अगर कोई इसी तरह के समाधान की तलाश में है तो यह मेरे लिए काम कर रहा है:

 g.append('svg:text')
  .attr('x', 0)
  .attr('y', 30)
  .attr('class', 'id')
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 5)
  .text(function(d) { return d.name; })
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 20)
  .text(function(d) { return d.sname; })
  .append('svg:tspan')
  .attr('x', 0)
  .attr('dy', 20)
  .text(function(d) { return d.idcode; })

वहाँ 3 लाइनों लाइनब्रेक के साथ अलग कर रहे हैं।


21
एफडब्ल्यूआईडब्ल्यू: ऐसा लगता है कि ओपी शुद्ध जावास्क्रिप्ट का उपयोग कर रहा था; यह उत्तर डी 3 का लाभ उठाता प्रतीत होता है ।
बेन मोशर

मैं डी 3 का उपयोग कर रहा हूं, और आपके दृष्टिकोण ने मेरे लिए काम किया। इसे पोस्ट करने के लिए धन्यवाद। मैंने पाया कि मुझे नए लोगों को जोड़ने से पहले पहले पुराने tspans को हटाने की आवश्यकता थी, इस तरह: focus.selectAll ("tspan")। remove ();
डैरेन पार्कर

1
इस दृष्टिकोण से सावधान रहें कि यह चैन से <tspan> टैग्स को नामांकित करता है ।append ()। यह सीएसएस के साथ कुछ मामूली सिरदर्द पैदा कर सकता है जो आप करना चाहते हैं उसके आधार पर।
सेनेयर

एक दृष्टिकोण के लिए यहां देखें जो @seneyr द्वारा वर्णित घोंसले के शिकार से बचा जाता है
bszom

16

Tspan समाधान के साथ, मान लें कि आप पहले से नहीं जानते हैं कि अपनी लाइन को कहाँ रखा जाए: आप इस अच्छे फंक्शन का उपयोग कर सकते हैं, जो मुझे यहाँ मिला: http://bl.ocks.org/mbostock/7555321

यह स्वचालित रूप से पिक्सेल में दी गई चौड़ाई के लिए लंबे पाठ svg के लिए लाइन ब्रेक करता है।

function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

9

मुझे लगता है कि यह वही करता है जो आप चाहते हैं:

function ShowTooltip(evt, mouseovertext){
    // Make tooltip text        
    var tooltip_text = tt.childNodes.item(1);
    var words = mouseovertext.split("\\\n");
    var max_length = 0;

    for (var i=0; i<3; i++){
        tooltip_text.childNodes.item(i).firstChild.data = i<words.length ?  words[i] : " ";
        length = tooltip_text.childNodes.item(i).getComputedTextLength();
        if (length > max_length) {max_length = length;}
    }

    var x = evt.clientX + 14 + max_length/2;
    var y = evt.clientY + 29;
    tt.setAttributeNS(null,"transform", "translate(" + x + " " + y + ")")

    // Make tooltip background
    bg.setAttributeNS(null,"width", max_length+15);
    bg.setAttributeNS(null,"height", words.length*15+6);
    bg.setAttributeNS(null,"x",evt.clientX+8);
    bg.setAttributeNS(null,"y",evt.clientY+14);

    // Show everything
    tt.setAttributeNS(null,"visibility","visible");
    bg.setAttributeNS(null,"visibility","visible");
}

यह पाठ को विभाजित करता है \\\nऔर प्रत्येक के लिए प्रत्येक खंड को त्सपान में रखता है। फिर यह पाठ की सबसे लंबी लंबाई और लाइनों की संख्या के आधार पर आवश्यक बॉक्स के आकार की गणना करता है। तीन tspans शामिल करने के लिए आपको टूलटिप पाठ तत्व को बदलने की भी आवश्यकता होगी:

<g id="tooltip" visibility="hidden">
    <text><tspan>x</tspan><tspan x="0" dy="15">x</tspan><tspan x="0" dy="15">x</tspan></text>
</g>

यह मानता है कि आपके पास कभी भी तीन से अधिक लाइनें नहीं हैं। यदि आप तीन से अधिक लाइनें चाहते हैं तो आप अधिक tspans जोड़ सकते हैं और लूप की लंबाई बढ़ा सकते हैं।


इसके "\\\n"बजाय क्यों है "\n"?
रैलिन

2

मैं थोड़ा @steco द्वारा समाधान ढाल लिया है, पर निर्भरता को स्विच करने d3के लिए jqueryऔर जोड़ने heightपैरामीटर के रूप में पाठ तत्व की

function wrap(text, width, height) {
  text.each(function(idx,elem) {
    var text = $(elem);
    text.attr("dy",height);
        var words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat( text.attr("dy") ),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (elem.getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

2

जावास्क्रिप्ट के बजाय HTML का उपयोग करें

<html>
  <head><style> * { margin: 0; padding: 0; } </style></head>
  <body>
    <h1>svg foreignObject to embed html</h1>

    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 300 300"
      x="0" y="0" height="300" width="300"
    >

      <circle
        r="142" cx="150" cy="150"
        fill="none" stroke="#000000" stroke-width="2"
      />

      <foreignObject
        x="50" y="50" width="200" height="200"
      >
        <div
          xmlns="http://www.w3.org/1999/xhtml"
          style="
            width: 196px; height: 196px;
            border: solid 2px #000000;
            font-size: 32px;
            overflow: auto; /* scroll */
          "
        >
          <p>this is html in svg 1</p>
          <p>this is html in svg 2</p>
          <p>this is html in svg 3</p>
          <p>this is html in svg 4</p>
        </div>
      </foreignObject>

    </svg>

</body></html>


मुझे लगता है कि आपका मतलब है "जावास्क्रिप्ट के बजाय SVG का उपयोग करें"
Valerio Bozz

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