2011-04-05 18 views
67

Ho la seguente rettangolo di ...come posizionare il testo e il centro in un rettangolo SVG

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

vorrei centrare la parola "fiction" all'interno di esso. Per gli altri rettangoli, fa svg word wrap per rimanere dentro di loro? Non riesco a trovare nulla di specifico sull'inserimento di testo all'interno di forme centrate sia orizzontalmente che verticalmente e il ritorno a capo automatico. Inoltre, il testo non può lasciare il rettangolo.

L'esempio http://www.w3.org/TR/SVG/text.html#TextElement non aiuta poiché le xey degli elementi di testo sono diverse dalle xey del rettangolo. Non sembra esserci larghezza e altezza per gli elementi di testo. Non sono sicuro della matematica qui.

(La mia tabella HTML non è solo andare a lavorare.)

risposta

32

SVG 1.2 Piccolo disposizione del testo aggiunto, ma la maggior parte delle implementazioni di SVG che troverete nel browser (con l'eccezione di Opera) non hanno attuato questo caratteristica. In genere spetta a te, lo sviluppatore, posizionare il testo manualmente.

La specifica SVG 1.1 fornisce una buona panoramica di questa limitazione, e le possibili soluzioni per superarla:

Ciascun elemento ‘testo’ provoca un singolo stringa di testo da generare. SVG non esegue il blocco automatico delle righe o il word wrapping . Per ottenere l'effetto di più righe di testo, utilizzare uno dei seguenti metodi:

  • Il pacchetto autore o di authoring deve di pre-calcolare le interruzioni di riga e utilizzare molteplici elementi di 'text' (uno per ciascuna riga di testo ).
  • L'autore o authoring pacchetto deve pre-calcolare la linea pause e utilizzare un singolo 'testo' elemento con uno o più 'tspan' bambino elementi con valori appropriati per 'x' attributi, 'y' , 'dx' e 'dy' a impostano nuove posizioni iniziali per quei caratteri che iniziano nuove righe. (Questo approccio consente testo utente selezione su più righe di testo -. Vedi selezione del testo e operazioni di appunti)
  • Esprimi il testo da rendere in un altro XML namespace come XHTML [XHTML] linea incorporato all'interno di un elemento 'foreignObject' . (Nota: i esatta semantica di questo approccio sono non completamente definite in questo momento.)

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

Come primitivo, disposizione testo può essere simulato utilizzando l'attributo dy ed elementi tspan e come menzionato nelle specifiche, alcuni strumenti possono automatizzarlo. Ad esempio, in Inkscape, seleziona la forma che desideri e il testo che desideri e utilizza Testo -> Flusso nel fotogramma. Questo ti permetterà di scrivere il tuo testo, con il wrapping, che si avvolgerà in base ai limiti della forma. Inoltre, assicurati di seguire queste istruzioni per dire a Inkscape di mantenere la compatibilità con SVG 1.1: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F

Inoltre, ci sono alcune librerie JavaScript che possono essere utilizzati per automatizzare dinamicamente la disposizione del testo: http://www.carto.net/papers/svg/textFlow/

E 'interessante notare la soluzione di CSVG ad avvolgere una forma a un elemento di testo (ad esempio, vedere il loro " pulsante" esempio), anche se è importante ricordare che la loro attuazione è non utilizzabile in un browser: http://www.csse.monash.edu.au/~clm/csvg/about.html

sto menzionare questo perché ho sviluppato una libreria CSVG di ispirazione che permette y Puoi fare cose simili e funziona nei browser web, anche se non l'ho ancora pubblicato.

+4

E non hanno nemmeno fatemi su quello che è coinvolto nella creazione di * * modificabile testo ... – jbeard4

+0

Grazie per la risposta ... ma ACK! Sembra che dovrò scaricare svg allora. Una delle prime cose che gli sviluppatori avrebbero dovuto pensare era allegare testo (formattato come gli utenti lo desiderano) alle forme! Aspetterò fino a quando non compiranno il loro atto prima che lo faccia più. Proverò a ridisegnarlo in Windows Paint e vedere se lo farà. (Se solo potessi ottenere i browser per visualizzare correttamente la tabella.) –

+0

Informazioni sul testo modificabile in svg, Opera supporta l'attributo modificabile da SVG 1.2 Tiny, che rende possibile ottenere il testo modificabile semplicemente aggiungendo un attributo 'editable =" true "' per l'elemento text o textArea. –

1

Ho avuto un sacco di tempo per ottenere qualcosa centrato usando SVG, quindi ho eseguito la mia piccola funzione. spero che dovrebbe aiutarti. Si noti che funziona solo per elementi 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); 
} 
83

Una soluzione semplice per centrare il testo in orizzontale e in verticale in SVG:

  1. impostare la posizione del testo al centro assoluto dell'elemento in cui si desidera centrarlo:

    • Se è il genitore, puoi semplicemente fare x="50%" y ="50%".
    • Se si tratta di un altro elemento, x sarebbe lo x di quell'elemento + metà della sua larghezza (e simile per ma con l'altezza).
  2. utilizza la proprietà text-anchor per centrare il testo orizzontalmente con il valore middle:

    mezzo

    I caratteri resi sono allineate in modo tale che il centro geometrico del testo reso risultante è nella posizione iniziale del testo corrente.

  3. utilizzare la proprietà alignment-baseline per centrare il testo verticalmente con il valore middle (o seconda di come si desidera guardare come, si consiglia di fare central)

Ecco una semplice demo:

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

+0

Ho cercato dappertutto una soluzione così semplice - nient'altro funzionava per me l'ho usato per centrare un numero all'interno di una barra di progresso radiale – anthonytherockjohnson

+3

Nel mio caso, è la proprietà 'dominante-base 'che fa il lavoro, non la "linea di base dell'allineamento". – pintoch

+0

Sfortunatamente, questa soluzione ritaglia il tratto del rettangolo. Vedere il mio esempio qui sotto per una soluzione che eviti il ​​clipping: https://stackoverflow.com/a/44857272/3795219 –

4

È possibile utilizzare direttamente la proprietà text-anchor = "middle". Ti consiglio di creare un elemento svg wrapper sul tuo rettangolo e testo. In questo modo puoi usare l'intero elemento usando un selettore di CSS. Assicurati di inserire la proprietà 'x' e 'y' del testo come 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> 
+0

modificato. Grazie. –

0

Un modo per inserire il testo all'interno di un rettangolo è quello di inserire un oggetto estraneo, che è una DIV, all'interno oggetto rett.

In questo modo, il testo rispetterà i limiti del DIV.

var g = d3.select("svg"); 
 
\t \t \t \t \t 
 
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>

+0

Benvenuti in Stack Overflow! Sentiti libero di fare un [tour] (// stackoverflow.com/tour) del sito, e se hai bisogno di ulteriore aiuto con il sito, controlla [this] (// stackoverflow.com/help). Oh, e se ti imbatti in problemi che la pagina di aiuto non copre, sentiti libero di chiedere su [meta] (// meta.stackoverflow.com/). –

5

Le risposte precedenti hanno dato scarsi risultati quando si utilizzano gli angoli arrotondati o stroke-width che è> 1. Ad esempio, ci si aspetta il seguente codice per la produzione di un rettangolo arrotondato, ma gli angoli sono ritagliati dalla componente principale 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>

Invece, vi consiglio di avvolgendo la text in un svg e poi nidificazione quella nuova svg e rect insieme all'interno di un elemento g, come il seguente esempio:

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

Questo corregge il problema di ritaglio che si verifica nelle risposte sopra. Ho anche tradotto il gruppo rect/text usando l'attributo transform="translate(x,y)" per dimostrare che questo fornisce un approccio più intuitivo al posizionamento del rect/testo sullo schermo.

2

tutti i dettagli Blog: 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>

+0

Non centrato in firefox mentre altre soluzioni sono. https://codepen.io/anon/pen/oEByYr – tgf

+0

Ho provato su Firefox 58.0.1 (64-bit), funziona. Puoi menzionare la versione per la quale non funziona per te? –

+0

Firefox 58.0.2 64 bit. Il testo è leggermente superiore a quello che dovrebbe essere. All'inizio potrebbe non essere facilmente percepibile, ma se la tua scatola si adatta molto da vicino è più ovvio; prova a ridurre l'altezza. – tgf

Problemi correlati