2012-02-11 4 views
20

Sto disegnando etichette di testo in SVG. Ho una larghezza fissa disponibile (ad esempio 200px). Quando il testo è troppo lungo, come posso tagliarlo?Ritaglio del testo a una determinata larghezza di pixel in SVG

La soluzione ideale aggiungerebbe anche puntini di sospensione (...) dove viene tagliato il testo. Ma posso anche vivere senza di essa.

+0

Quale motore SVG stai scegliendo? Adobe? WebKit? Firefox? IE9? – Gabe

+0

È per un'applicazione Web, quindi mi rivolgo a WebKit, Firefox, IE9. – Blacksad

risposta

26

Un modo per fare ciò è utilizzare un elemento textPath, poiché tutti i caratteri che cadono dal percorso verranno ritagliati automaticamente. Vedere il percorso di testo examples dalla suite di test SVG.

Un altro modo è utilizzare CSS3 text-overflow su elementi di testo svg, un esempio here. Opera 11 lo supporta, ma probabilmente scoprirai che gli altri browser lo supportano solo su elementi html in questo momento.

Puoi anche misurare le stringhe di testo e inserire i puntini di sospensione con lo script, suggerirei di utilizzare il metodo getSubStringLength sull'elemento di testo, aumentando il parametro nchars fino a trovare una lunghezza che sia adatta. 3 ° suggerimento

+0

L'esempio CSS3 non funziona per me. Né il trabocco del testo o il percorso del testo sembrano ritagliare l'overflow. Qualcosa è cambiato? –

+0

@DavidMeza purtroppo "text-overflow" (ancora) non è supportato negli elementi di testo svg, https://bugs.chromium.org/p/chromium/issues/detail?id=366550 –

+0

@ ErikDahlström Grazie, il primo il metodo ha funzionato alla grande! Ne ho giocherellato un po 'perché al mio primo tentativo non usavo valori univoci nelle associazioni 'xlink: href' -' id'. –

17

Implementazione di Erik mi si avvicinò con qualcosa di simile:

//places textString in textObj, adds an ellipsis if text can't fit in width 
function placeTextWithEllipsis(textObj,textString,width){ 
    textObj.textContent=textString; 

    //ellipsis is needed 
    if (textObj.getSubStringLength(0,textString.length)>=width){ 
     for (var x=textString.length-3;x>0;x-=3){ 
      if (textObj.getSubStringLength(0,x)<=width){ 
       textObj.textContent=textString.substring(0,x)+"..."; 
       return; 
      } 
     } 
     textObj.textContent="..."; //can't place at all 
    } 
} 

sembra fare il trucco :)

+0

Questo ha funzionato per me, ma devi fare certo il nodo è già stato reso nella dom. Quindi fai attenzione quando aggiungi dinamicamente i nodi. – borisrorsvort

+0

@borisrorsvort in realtà ho riscontrato lo stesso problema. Hai trovato una soluzione per l'esecuzione su nodi non renderizzati? – OpherV

+0

Alla fine della funzione di aggiornamento classica, eseguo il loop di tutti i nodi, quindi utilizzo la funzione. Quindi, quando arrivano nuovi nodi, rieseguo il metodo di aggiornamento. https://gist.github.com/borisrorsvort/cc6ada7e4cbfc7f959b9 – borisrorsvort

18

Utilizzando biblioteca d3

una funzione wrapper per il testo traboccante:

function wrap() { 
     var self = d3.select(this), 
      textLength = self.node().getComputedTextLength(), 
      text = self.text(); 
     while (textLength > (width - 2 * padding) && text.length > 0) { 
      text = text.slice(0, -1); 
      self.text(text + '...'); 
      textLength = self.node().getComputedTextLength(); 
     } 
    } 

utilizzo:

text.append('tspan').text(function(d) { return d.name; }).each(wrap); 
+0

La domanda non menziona d3. –

+16

... ma aiuta le persone che sono arrivate qui con lo stesso problema, e usando d3 :) – inolasco

+0

Dovresti inserire questa risposta in un Gist o qualcosa del genere così puoi [copia incolla] (http://stackoverflow.com/a/27723752/279259) più veloce la prossima volta. – ereOn

3

@ user2846569 mostrami come farlo (sì, utilizzando d3.js). Ma, devo fare alcune piccole modifiche al lavoro:


     function wrap(d) { 
       var self = d3.select(this), 
        textLength = self.node().getComputedTextLength(), 
        text = self.text(); 
       while ((textLength > self.attr('width'))&& text.length > 0) { 
        text = text.slice(0, -1); 
        self.text(text + '...'); 
        textLength = self.node().getComputedTextLength(); 
       } 
      } 
      svg.append('text') 
       .append('tspan') 
       .text(function(d) { return d; }) 
       .attr('width', 200) 
       .each(wrap); 
+0

La soluzione di @ user2846569 ha funzioni vars che non esistono. Utilizzare invece questa soluzione modificata. –

1

provare questo, io uso questa funzione nella mia biblioteca tabella:

function textEllipsis(el, text, width) { 
    if (typeof el.getSubStringLength !== "undefined") { 
    el.textContent = text; 
    var len = text.length; 
    while (el.getSubStringLength(0, len--) > width) {} 
    el.textContent = text.slice(0, len) + "..."; 
    } else if (typeof el.getComputedTextLength !== "undefined") { 
    while (el.getComputedTextLength() > width) { 
     text = text.slice(0,-1); 
     el.textContent = text + "..."; 
    } 
    } else { 
    // the last fallback 
    while (el.getBBox().width > width) { 
     text = text.slice(0,-1); 
     // we need to update the textContent to update the boundary width 
     el.textContent = text + "..."; 
    } 
    } 
} 
0

Il mio approccio è stato simile a OpherV di, ma ho provato a fare questo utilizzando jQuery

function getWidthOfText(text, fontSize, fontFamily) { 
 
    var span = $('<span></span>'); 
 
    span.css({ 
 
     'font-family': fontFamily, 
 
     'font-size' : fontSize 
 
    }).text(text); 
 
    $('body').append(span); 
 
    var w = span.width(); 
 
    span.remove(); 
 
    return w; 
 
} 
 

 
function getStringForSize(text, desiredSize, fontSize, fontFamily) { 
 
    var curSize = getWidthOfText(text, fontSize, fontFamily); 
 
    if(curSize > size) 
 
    { 
 
     var curText = text.substring(0,text.length-5) + '...'; 
 
     return getStringForSize(curText, size, fontSize, fontFamily); 
 
    } 
 
    else 
 
    { 
 
     return text; 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Ora quando chiami getStringForSize('asdfasdfasdfasdfasdfasdf', 110, '13px','OpenSans-Light') otterrai "asdfasdfasdfasd ..."

Problemi correlati