एसवीजी आयत में टेक्स्ट को कैसे रखें और कैसे रखें


179

मेरे पास निम्नलिखित आयत है ...

<rect x="0px" y="0px" width="60px" height="20px"/>

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

को देखते हुए http://www.w3.org/TR/SVG/text.html#TextElement उदाहरण के बाद से पाठ तत्व के एक्स नहीं मदद करता है और y से आयत के x और y अलग हैं। पाठ तत्वों के लिए चौड़ाई और ऊंचाई प्रतीत नहीं होती है। मुझे यहां गणित का यकीन नहीं है।

(मेरी html तालिका अभी काम की नहीं है।)


1
क्या आप टेक्स्ट-एंकर और प्रमुख-बेसलाइन का उपयोग करके उत्तर पर स्विच कर सकते हैं? धन्यवाद!
neaumusic

1
neaumusic, किया। 8)
लेडी एलेना

जवाबों:


310

एसवीजी में क्षैतिज और लंबवत रूप से केंद्र के लिए एक आसान समाधान:

  1. उस तत्व के पूर्ण केंद्र पर पाठ की स्थिति सेट करें जिसमें आप इसे केन्द्रित करना चाहते हैं:

    • यदि यह माता-पिता है, तो आप बस कर सकते हैं x="50%" y ="50%"
    • यदि यह एक और तत्व है, xतो xउस तत्व का आधा भाग + उसकी चौड़ाई (और yऊंचाई के साथ समान ) होगा।
  2. text-anchorमूल्य के साथ टेक्स्ट को क्षैतिज रूप से केंद्र में रखने के लिए संपत्ति का उपयोग करें middle:

    मध्य

    प्रदान किए गए वर्ण इस तरह संरेखित किए जाते हैं कि परिणामी पाठ का ज्यामितीय मध्य प्रारंभिक वर्तमान पाठ स्थिति पर होता है।

  3. dominant-baselineमूल्य के साथ पाठ को केंद्र में रखने के लिए संपत्ति का उपयोग करें middle(या आप इसे कैसे दिखना चाहते हैं इसके आधार पर, आप ऐसा करना चाह सकते हैं central)

यहाँ एक सरल डेमो है:

<svg width="200" height="100">
  <rect x="0" y="0" width="200" height="100" stroke="red" stroke-width="3px" fill="white"/>
  <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">TEXT</text>    
</svg>


1
मैं हर जगह इस सरल समाधान के लिए देख रहा हूं - मेरे लिए और कुछ भी काम नहीं कर रहा था मैंने इसका उपयोग एक रेडियल प्रगति पट्टी के अंदर एक संख्या को केंद्रित करने के लिए किया था
एंथोनीथेरॉकजोनसन

7
मेरे मामले में, यह dominant-baselineसंपत्ति है जो काम करती है, नहीं alignment-baseline
पिंटोच

1
यदि आप नियमित रूप से ऐसा करने जा रहे हैं, तो आप निम्नलिखित भी जोड़ सकते हैं <style type="text/css"><![CDATA[ text { alignment-baseline: middle; text-anchor:middle; } ]]></style>:। समाधान के लिए धन्यवाद।
मंजींगो

1
अपना कोड स्निपेट चलाएं। यह काम नहीं करता है। इसे देखें: यह स्टैकओवरफ्लो द्वारा प्रदान किए गए पूर्वावलोकन में भी काम नहीं करता है। जैसा कि टिप्पणी में पहले कहा गया है कि dominant-baselineवास्तव में इसका उपयोग करने की आवश्यकता है। मुझे खेद है, लेकिन यह जवाब किसी तरह भ्रामक है। जैसा कि यह फ़ायरफ़ॉक्स और न ही क्रोमियम में काम करने के लिए प्रतीत नहीं होता है और इसके अलावा आपको टिप्पणियों का अध्ययन करना चाहिए ताकि अपने दम पर सही समाधान खोजने के लिए मैंने कोड के साथ एक और उत्तर जोड़ने की स्वतंत्रता ली जो अपेक्षित रूप से काम करता है। (रिकॉर्ड्स के लिए: उबंटू लिनक्स पर एफएफ और क्रोमियम के साथ परीक्षण किया गया।)
रेजिस मई

2
@RegisMay इसे इंगित करने के लिए धन्यवाद। मैं क्रोम मैक पर पर हूँ और इसके साथ ठीक काम किया alignment-baseline, लेकिन ऐसा लगता है कि यह एक विचित्र बात यह है कि क्योंकि चश्मा समीक्षा करते समय, यह होना चाहिए हो सकता है dominant-baselineके लिए text, और alignment-baselineके लिए tspan, tref, altGlyph, और textPath। मैंने उसी हिसाब से जवाब अपडेट किया।
अल्वारो मोंटोरो

38

एसवीजी 1.2 टिनी ने टेक्स्ट रैपिंग को जोड़ा, लेकिन एसवीजी के अधिकांश कार्यान्वयन जो आपको ब्राउज़र में मिलेंगे (ओपेरा के अपवाद के साथ) इस सुविधा को लागू नहीं किया है। यह आम तौर पर आप पर निर्भर है, डेवलपर, पाठ को मैन्युअल रूप से स्थिति में लाने के लिए।

एसवीजी 1.1 विनिर्देश इस सीमा का एक अच्छा अवलोकन और इसे दूर करने के लिए संभावित समाधान प्रदान करता है:

प्रत्येक 'टेक्स्ट' एलिमेंट में टेक्स्ट के सिंगल स्ट्रिंग को प्रस्तुत किया जाता है। एसवीजी कोई स्वचालित लाइन ब्रेकिंग या वर्ड रैपिंग नहीं करता है। पाठ की कई पंक्तियों के प्रभाव को प्राप्त करने के लिए, निम्न विधियों में से एक का उपयोग करें:

  • लेखक या संलेखन पैकेज को लाइन ब्रेक की पूर्व-गणना करने और कई 'टेक्स्ट' तत्वों (टेक्स्ट की प्रत्येक पंक्ति के लिए एक) का उपयोग करने की आवश्यकता होती है।
  • लेखक या संलेखन पैकेज को पंक्ति विराम की पूर्व-गणना करने और विशेषताओं 'x', 'y', 'dx' और 'dy' के लिए उपयुक्त मानों के साथ एक या अधिक 'tspan' बाल तत्वों के साथ एक 'टेक्स्ट' तत्व का उपयोग करने की आवश्यकता होती है। उन पात्रों के लिए नई शुरुआत की स्थिति निर्धारित करने के लिए जो नई लाइनें शुरू करते हैं। (यह दृष्टिकोण पाठ की कई पंक्तियों में उपयोगकर्ता पाठ चयन की अनुमति देता है - पाठ चयन और क्लिपबोर्ड संचालन देखें।)
  • एक्सएमएल [एक्सएचटीएमएल] जैसे किसी अन्य एक्सएमएल नेमस्पेस में प्रस्तुत किए जाने वाले टेक्स्ट को एक 'विदेशी ऑबजेक्ट' तत्व के भीतर इनलाइन करें। (नोट: इस दृष्टिकोण के सटीक शब्दार्थ इस समय पूरी तरह से परिभाषित नहीं हैं।)

http://www.w3.org/TR/SVG11/text.html#Introduction

एक आदिम के रूप में, टेक्स्ट रैपिंग को dyविशेषता और tspanतत्वों का उपयोग करके अनुकरण किया जा सकता है , और जैसा कि कल्पना में बताया गया है, कुछ उपकरण इसे स्वचालित कर सकते हैं। उदाहरण के लिए, Inkscape में, इच्छित आकृति का चयन करें, और जिस पाठ को आप चाहते हैं, और पाठ का उपयोग करें -> फ़्रेम में प्रवाह करें। यह आपको अपने पाठ को लिखने की अनुमति देगा, रैपिंग के साथ, जो आकार की सीमा के आधार पर लपेटेगा। इसके अलावा, सुनिश्चित करें कि आप एसवीजी 1.1 के साथ संगतता बनाए रखने के लिए इनस्केप को बताने के लिए इन निर्देशों का पालन करें: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

इसके अलावा, कुछ जावास्क्रिप्ट पुस्तकालय हैं जिनका उपयोग पाठ रैपिंग को गतिशील रूप से स्वचालित करने के लिए किया जा सकता है: http://www.carto.net/papers/svg/textFlow/

किसी पाठ तत्व को आकार देने के लिए CSVG के समाधान पर ध्यान देना दिलचस्प है (उदाहरण के लिए उनका "बटन" उदाहरण देखें), हालांकि यह उल्लेख करना महत्वपूर्ण है कि उनका कार्यान्वयन किसी ब्राउज़र में उपयोग करने योग्य नहीं है: http://www.csse.monash.edu .au / ~ clm / csvg / about.html

मैं इसका उल्लेख कर रहा हूं क्योंकि मैंने एक सीएसवीजी-प्रेरित पुस्तकालय विकसित किया है जो आपको इसी तरह की चीजें करने की अनुमति देता है और वेब ब्राउज़र में काम करता है, हालांकि मैंने इसे अभी तक जारी नहीं किया है।


उत्तर के लिए धन्यवाद ... लेकिन ACK! ऐसा प्रतीत होता है कि मुझे svg को डंप करना पड़ेगा। पहली चीजों में से एक जिसे डेवलपर्स को आकार में पाठ (उपयोगकर्ता की इच्छानुसार स्वरूपित) संलग्न करना चाहिए था! मैं तब तक इंतजार करूंगा जब तक कि वे इससे पहले कि मैं इसके साथ अपना अभिनय नहीं कर लेता। मैं इसे विंडोज पेंट में फिर से शुरू करने की कोशिश करूंगा और देखूंगा कि क्या यह ऐसा करेगा। (यदि केवल मैं ही तालिका को सही ढंग से प्रदर्शित करने के लिए ब्राउज़रों को प्राप्त कर सका।)
लेडी एलेना

Svg में संपादन योग्य पाठ के बारे में, ओपेरा SVG 1.2 टिनी से संपादन योग्य विशेषता का समर्थन करता है, जो केवल editable="true"पाठ या textArea तत्व में एक विशेषता जोड़कर संपादन योग्य पाठ प्राप्त करना संभव बनाता है ।
एरिक डहलस्ट्रम

2
@ एरिक, एक बार फिर ओपेरा वक्र से आगे है।
jbeard4

@Lady अलेना, मैं सिर्फ मानसिक रूप से Inkscape समाधान का उपयोग क्यों नहीं करता? यदि यह सिर्फ एक स्थिर छवि है (उदाहरण के लिए कोई गतिशील व्यवहार नहीं, पाठ सामग्री को गतिशील रूप से अपडेट नहीं करना), तो यह ठीक काम करना चाहिए। इसके अलावा, यह स्केलेबल होगा, जो पेंट नहीं करेगा, क्योंकि पेंट रास्टर ग्राफिक्स का उत्पादन करता है। अंत में, मुझे विश्वास नहीं होता कि पेंट किसी भी स्तर पर पाठ रैपिंग का समर्थन करता है।
jbeard4

@ इको-फ्लो मैं कोड उत्पन्न करने वाले कार्यक्रमों में बहुत समय पहले विश्वास खो दिया था क्योंकि मैंने html उत्पन्न करने के लिए (और बाद में डंप किया) Microsoft फ्रंट पेज का उपयोग किया था। मैं हमेशा कार्यक्रमों से सावधान रहता हूं कि मैं जो लिख रहा हूं उसमें अपना खुद का मालिकाना कोड जोड़ रहा हूं। फ्रंट पेज ने वास्तव में मेरे HTML को गड़बड़ कर दिया। यदि आप एक Inkscape उपयोगकर्ता हैं, तो क्या आप मुझे बता सकते हैं कि यदि Inkscape ने svg में अपना स्वामित्व कोड रखा है, तो मुझे svg के निर्माण के बाद बाहर जाना होगा और पट्टी करनी होगी?
बजे लेडी एलेना

23

पिछले उत्तर गोल कोनों का उपयोग करते समय खराब परिणाम देते हैं या stroke-widthयह> 1 है। उदाहरण के लिए, आप निम्न कोड की अपेक्षा करेंगे कि एक गोल आयत का निर्माण किया जाए, लेकिन कोनों को मूल svgघटक द्वारा क्लिप किया जाता है :

<svg width="200" height="100">
  <!--this rect should have rounded corners-->
  <rect x="0" y="0" rx="5" ry="5" width="200" height="100" stroke="red" stroke-width="10px" fill="white"/>
  <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CLIPPED BORDER</text>    
</svg>

इसके बजाय, मैं लपेटकर की सलाह देते हैं textएक में svgऔर फिर उस नए घोंसले svgऔर rectएक साथ एक के अंदर gतत्व, निम्न उदाहरण में:

<!--the outer svg here-->
<svg width="400px" height="300px">

  <!--the rect/text group-->
  <g transform="translate(50,50)">
    <rect rx="5" ry="5" width="200" height="100" stroke="green" fill="none" stroke-width="10"/>
    <svg width="200px" height="100px">
      <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">CORRECT BORDER</text>      
    </svg>
  </g>

  <!--rest of the image's code-->
</svg>

यह क्लिपिंग समस्या को ठीक करता है जो उपरोक्त उत्तरों में होती है। मैंने यह transform="translate(x,y)"दिखाने के लिए विशेषता का उपयोग करते हुए कि आयत / पाठ समूह का अनुवाद किया है, यह आयत / पाठ को ऑन-स्क्रीन पोजिशन करने के लिए अधिक सहज दृष्टिकोण प्रदान करता है।


16

यदि आप एसवीजी प्रोग्रामेटिक रूप से बना रहे हैं तो आप इसे सरल बना सकते हैं और कुछ इस तरह से कर सकते हैं:

  <g>
      <rect x={x} y={y} width={width} height={height} />
      <text
          x={x + width / 2}
          y={y + height / 2}
          dominant-baseline="middle"
          text-anchor="middle"
      >
          {label}
      </text>
  </g>

3
Shouldsn't यह dominant-baselineऔर text-anchor, नहीं dominantBaselineऔर textAnchor?
नाथनियल एम। बेवर

1
@ नथानिएल.बीवर हां, यह होना चाहिए। अच्छी पकड़। उपरोक्त कोड रिएक्ट से है जिसे दुर्भाग्य से कैमलकेस का उपयोग करके नाम बदलने की आवश्यकता है।
ब्रेनन चेउंग

13

आप सीधे text-anchor = "middle"संपत्ति का उपयोग कर सकते हैं। मैं आपके आयत और पाठ पर एक आवरण svg तत्व बनाने की सलाह देता हूं। इस तरह आप एक सीएसएस चयनकर्ता का उपयोग करके पूरे तत्व का उपयोग कर सकते हैं। सुनिश्चित करें कि आपने पाठ की 'x' और 'y' संपत्ति को 50% पर रखा है।

    <svg class="svg-rect" width="50" height="40">
        <rect x="0" y="0" rx="3" ry="3" width="50" height="40" fill="#e7e7e7"></rect>
        <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="1px" dy=".3em">N/A</text>
    </svg>


7

पूर्ण विवरण ब्लॉग: http://blog.techhysahil.com/svg/how-to-center-text-in-svg-shapes/

<svg width="600" height="600">
  <!--   Circle -->
  <g transform="translate(50,40)">
    <circle cx="0" cy="0" r="35" stroke="#aaa" stroke-width="2" fill="#fff"></circle>
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  <!--   In Rectangle text position needs to be given half of width and height of rectangle respectively -->
  <!--   Rectangle -->
  <g transform="translate(150,20)">
    <rect width="150" height="40" stroke="#aaa" stroke-width="2" fill="#fff"></rect>
    <text x="75" y="20" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  <!--   Rectangle -->
  <g transform="translate(120,140)">
    <ellipse cx="0" cy="0" rx="100" ry="50" stroke="#aaa" stroke-width="2" fill="#fff"></ellipse>
    <text x="0" y="0" alignment-baseline="middle" font-size="12" stroke-width="0" stroke="#000" text-anchor="middle">HueLink</text>
  </g>
  
  
</svg>


फ़ायरफ़ॉक्स में केंद्रित नहीं है जबकि अन्य समाधान हैं। codepen.io/anon/pen/oEByYr
tgf

मैंने फ़ायरफ़ॉक्स 58.0.1 (64-बिट) पर परीक्षण किया, यह काम कर रहा है। क्या आप उस संस्करण का उल्लेख कर सकते हैं जिसके लिए वह आपके लिए काम नहीं कर रहा है?
साहिल गुप्ता

फ़ायरफ़ॉक्स 58.0.2 64 बिट। पाठ जितना होना चाहिए उससे थोड़ा अधिक है। यह पहली बार में आसानी से ध्यान देने योग्य नहीं हो सकता है, लेकिन यदि आपका बॉक्स बहुत बारीकी से फिट बैठता है तो यह अधिक स्पष्ट है; ऊंचाई कम करने का प्रयास करें।
tgf

6

alignment-baselineयहाँ उपयोग करने के लिए सही विशेषता नहीं है। सही जवाब के संयोजन का उपयोग करने के लिए है dominant-baseline="central"और text-anchor="middle":

<svg width="200" height="100">
    <g>
        <rect x="0" y="0" width="200" height="100" style="stroke:red; stroke-width:3px; fill:white;"/>
        <text x="50%" y="50%" style="dominant-baseline:central; text-anchor:middle; font-size:40px;">TEXT</text>
    </g>
</svg>


2

एक आयत के अंदर पाठ सम्मिलित करने का एक तरीका विदेशी वस्तु को सम्मिलित करना है, जो कि एक DIV है, जो रेक्ट ऑब्जेक्ट के अंदर है।

इस तरह, पाठ DIV की सीमाओं का सम्मान करेगा।

var g = d3.select("svg");
					
g.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width","100%")
.attr("height","100%")
.attr("fill","#000");


var fo = g.append("foreignObject")
 .attr("width","100%");

fo.append("xhtml:div")
  .attr("style","width:80%;color:#FFF;margin-right: auto;margin-left: auto;margin-top:40px")
  .text("Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis Mussum Ipsum, cacilds vidis litro abertis");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.js"></script>
<svg width="200" height="200"></svg>


1

मैं एसवीजी का उपयोग करके कुछ भी केंद्रित हो रहा था, तो मैं अपने छोटे से समारोह में लुढ़का हुआ था। उम्मीद है कि यह आपकी मदद करनी चाहिए। ध्यान दें कि यह केवल एसवीजी तत्वों के लिए काम करता है।

function centerinparent(element) { //only works for SVG elements
    var bbox = element.getBBox();
    var parentwidth = element.parentNode.width.baseVal.value;
    var parentheight = element.parentNode.height.baseVal.value;
    var newwidth = ((parentwidth / 2) - (bbox.width / 2)) - 2; //i start everything off by 2 to account for line thickness
    var newheight = ((parentheight / 2) - (bbox.height / 2)) - 2;
    //need to adjust for line thickness??

    if (element.classList.contains("textclass")) { //text is origined from bottom left, whereas everything else origin is top left
        newheight += bbox.height; //move it down by its height
    }

    element.setAttributeNS(null, "transform", "translate(" + newwidth + "," + newheight + ")");
    // console.log("centering BOXES:  between width:"+element.parentNode.width.baseVal.value + "   height:"+parentheight);
    // console.log(bbox);
}

1

ग्राफिक्स में पाठ के क्षैतिज और ऊर्ध्वाधर संरेखण के लिए, आप निम्नलिखित सीएसएस शैलियों का उपयोग करना चाह सकते हैं। विशेष रूप से, ध्यान दें कि dominant-baseline:middleशायद गलत है, क्योंकि यह (आमतौर पर) शीर्ष और आधार रेखा के बीच का आधा रास्ता है, बल्कि ऊपर और नीचे के बीच का आधा रास्ता। इसके अलावा, कुछ स्रोतों (जैसे मोज़िला ) के dominant-baseline:hangingबजाय का उपयोग करें dominant-baseline:text-before-edge। यह भी शायद गलत है, क्योंकि hangingइंडिक स्क्रिप्ट के लिए डिज़ाइन किया गया है। बेशक, यदि आप लैटिन, इंडिक, विचारधारा या जो कुछ भी मिश्रण का उपयोग कर रहे हैं, तो आपको शायद दस्तावेज़ पढ़ने की आवश्यकता होगी ।

/* Horizontal alignment */
text.goesleft{text-anchor:end}
text.equalleftright{text-anchor:middle}
text.goesright{text-anchor:start}
/* Vertical alignment */
text.goesup{dominant-baseline:text-after-edge}
text.equalupdown{dominant-baseline:central}
text.goesdown{dominant-baseline:text-before-edge}
text.ruledpaper{dominant-baseline:alphabetic}

संपादित करें: मैंने अभी देखा है कि मोज़िला भी उपयोग करता है dominant-baseline:baselineजो निश्चित रूप से गलत है: यह एक मान्यता प्राप्त मूल्य भी नहीं है! मुझे लगता है कि यह फ़ॉन्ट डिफ़ॉल्ट के लिए डिफ़ॉल्ट है, जो हैalphabetic , इसलिए वे भाग्यशाली हैं।

अधिक संपादित करें: सफारी (11.1.2) समझता है text-before-edgeलेकिन नहीं text-after-edge। यह भी विफल रहता है ideographic। महान सामान, Apple। तो आप alphabeticसभी के बाद descenders का उपयोग करने और अनुमति देने के लिए मजबूर हो सकते हैं । माफ़ करना।

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