Comment placer et centrer du texte dans un rectangle SVG

j'ai le rectangle suivant...

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

j'aimerais centrer le mot" Fiction " à l'intérieur. Pour les autres rectangles, est-ce que svg word s'enroule pour y rester? Je n'arrive pas à trouver quoi que ce soit spécifiquement sur l'insertion de texte dans des formes qui sont centrées à la fois horizontalement et verticalement et Word wrap. Aussi, le texte ne peut pas quitter le rectangle.

en regardant le http://www.w3.org/TR/SVG/text.html#TextElement L'exemple n'aide pas puisque les x et y de l'élément texte sont différents des X et y du rectangle. Il ne semble pas y avoir de largeur et de hauteur pour les éléments de texte. Je ne suis pas sûr du calcul ici.

(ma table html ne va tout simplement pas fonctionner.)

78
demandé sur Lady Aleena 2011-04-05 06:00:26

7 réponses

SVG 1.2 minuscule ajout d'un emballage de texte, mais la plupart des implémentations de SVG que vous trouverez dans le navigateur (à l'exception de Opera) n'ont pas implémenté cette fonctionnalité. C'est généralement à vous, le développeur, de positionner le texte manuellement.

la spécification SVG 1.1 donne un bon aperçu de cette limitation et des solutions possibles pour la surmonter:

chaque élément "text" provoque une chaîne de texte à rendre. SVG ne coupe pas automatiquement la ligne ou le mot de l'emballage. Pour obtenir l'effet de plusieurs lignes de texte, utilisez l'une des les méthodes suivantes:

  • L'auteur ou de création de package besoins pour pré-calculer les sauts de ligne et l'utilisation plusieurs ‘texte’ éléments (un pour chaque ligne de texte).
  • L'auteur ou de création paquet a besoin de calculer la ligne casse et utilise un seul élément "text" avec un ou plusieurs ‘tspan’ enfant éléments avec des valeurs appropriées pour les attributs ‘x’, ‘y’, ‘dx’ et ‘dy’ à établir de nouvelles positions de départ pour ceux caractères qui démarrent de nouvelles lignes. (Cette approche permet le texte utilisateur sélection à travers plusieurs lignes de texte -- voir sélection du texte et opérations de presse-papiers.)
  • expriment le texte à rendre dans un autre XML namespace tel que XHTML [XHTML] intégré inline dans un ‘foreignObject’ élément. (Note: le sémantique exacte de cette approche sont pas complètement défini pour le moment.)

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

comme un primitif, l'enrubannage de texte peut être simulé en utilisant l'attribut dy et les éléments tspan, et comme mentionné dans le spec, certains outils peuvent automatiser cela. Par exemple, dans Inkscape, sélectionnez la forme que vous voulez, et le texte que vous voulez, et utilisez Text -> Flow into Frame. Cela vous permettra pour écrire votre texte, avec emballage, qui sera enveloppé en fonction des limites de la forme. Aussi, assurez-vous de suivre ces instructions pour dire à Inkscape de maintenir la compatibilité avec SVG 1.1: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

de plus, il existe certaines bibliothèques JavaScript qui peuvent être utilisées pour automatiser dynamiquement l'enrubannage de texte: http://www.carto.net/papers/svg/textFlow /

il est intéressant de noter la solution de CSVG pour envelopper une forme dans un élément de texte (par exemple voir leur exemple de "bouton"), bien qu'il soit important de mentionner que leur mise en œuvre est et non utilisable dans un navigateur: http://www.csse.monash.edu.au/~clm/csvg/about.html

je mentionne ceci parce que j'ai développé une bibliothèque inspirée de CSVG qui vous permet de faire des choses similaires et fonctionne dans le web navigateurs, bien que je ne l'ai pas encore publié.

35
répondu jbeard4 2011-04-05 04:10:10

une solution facile pour centrer le texte horizontalement et verticalement dans SVG:

  1. placez la position du texte au centre absolu de l'élément dans lequel vous voulez le centrer:

    • si c'est le parent, vous pouvez juste faire x="50%" y ="50%" .
    • Si c'est un autre élément, x serait le x de cet élément + la moitié de sa largeur (et similaire pour y mais avec la hauteur).
  2. utilisez la text-anchor propriété pour centrer le texte horizontalement avec la valeur middle :

    moyen

    les caractères rendus sont alignés de telle sorte que le milieu géométrique du texte rendu soit à la position initiale du texte en cours.

  3. utilisez la alignment-baseline propriété pour centrer le texte verticalement avec la valeur middle (ou selon comment vous voulez qu'il ressemble, vous pouvez vouloir faire central )

Voici une démo simple:

<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%" alignment-baseline="middle" text-anchor="middle">TEXT</text>    
</svg>
112
répondu Alvaro Montoro 2015-07-20 16:50:07

les réponses précédentes donnaient de mauvais résultats lorsqu'on utilisait les coins arrondis ou stroke-width c'est-à-dire >1 . Par exemple, vous vous attendriez à ce que le code suivant produise un rectangle arrondi, mais les coins sont coupés par le parent svg composant:

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

au lieu de cela, je recommande d'envelopper le text dans un svg et puis d'emboîter ce nouveau svg et le rect ensemble à l'intérieur d'un g élément, comme dans l'exemple suivant:

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

cela corrige le problème de coupure qui se produit dans les réponses ci-dessus. J'ai aussi traduit le groupe Texte/rect en utilisant l'attribut transform="translate(x,y)" pour démontrer que cela fournit une approche plus intuitive pour positionner le texte/rect à l'écran.

10
répondu Austin D 2017-07-01 04:16:16

vous pouvez utiliser directement la propriété text-anchor = "middle" . Je conseille de créer un élément wrapper svg sur votre rectangle et votre texte. De cette façon, vous pouvez utiliser l'ensemble de l'élément en utilisant un sélecteur css. Assurez-vous de placer 'x' et 'y' propriété du texte comme 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>
5
répondu Nalin Agrawal 2016-08-13 19:47:45

blogue complet : 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>

5
répondu Sahil Gupta 2017-11-15 23:50:04

Une façon d'insérer du texte à l'intérieur d'un rectangle et d'insérer un objet étranger, ce qui est une DIV à l'intérieur rect objet.

ainsi, le texte respectera les limites du 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>
2
répondu Bruno Bastos 2017-06-20 15:05:30

j'ai eu un bugger d'un temps obtenir n'importe quoi centré en utilisant SVG, donc j'ai roulé ma propre petite fonction. j'espère que ça devrait vous aider. Notez que cela ne fonctionne que pour les éléments SVG.

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
répondu john ktejik 2015-01-14 21:11:10