Esercitazione di testo SVG: annotazione di testo sul Web

Pubblicato: 2022-03-11

Con HTML5 e CSS3, i browser web hanno acquisito una serie di tecnologie straordinarie: grafica 3D, socket, thread e altro ancora. Con questi, le applicazioni Web possono sfruttare alcune delle capacità più sofisticate dei computer e dei sistemi operativi su cui vengono utilizzate. Il browser Web offre un ecosistema robusto e versatile per lo sviluppo di applicazioni, il che è evidente dal recente aumento di numerose potenti applicazioni Web di cui non possiamo fare a meno. Tuttavia, qualcosa che ancora manca è la bellezza dell'annotazione e della decorazione del testo HTML. Cos'è la decorazione del testo? Sottolineature ondulate, evidenziazioni irregolari e barrature ondulate sono alcune delle cose di cui i browser Web non forniscono supporto nativo. Può sembrare più elaborato che utile, ma la capacità degli sviluppatori JavaScript di produrre questi stili può rivelarsi utile in aspetti come le risorse di e-learning e i lettori di ebook basati sul web. Inoltre, ciò può contribuire a migliorare l'esperienza dell'utente nelle applicazioni Web che ruotano attorno a principi di progettazione naturali. Per lo meno, costruire uno strumento del genere è divertente e fornisce informazioni sulle molte stranezze di un browser web.

Tutorial di testo SVG - annotazione di testo

Gli sviluppatori hanno trovato molte soluzioni alternative alla limitazione del browser web. Molte di queste soluzioni comportano l'uso di CSS in modi meno intuitivi, poiché alcuni usano immagini negli pseudo elementi “::after”. Funziona, ma mantenere molte immagini per ogni coppia stile-colore spesso si rivela difficile. Questo articolo esamina l'anatomia di una libreria JavaScript che cerca di risolvere questo problema in modo elegante.

La libreria è open source ed è disponibile su GitHub: Text Annotator

Panoramica

Durante lo sviluppo di questa libreria, è stata prestata particolare attenzione a garantire la compatibilità con i browser Web più diffusi (incluso IE 9+). Tuttavia, a differenza di come la maggior parte risolve questo problema, la libreria non si basa su trucchi CSS specificamente oscuri; o peggio, simboli Unicode speciali. Invece usa SVG per ottenere decorazioni di testo molto migliori e più pulite.

Fondamentalmente, la libreria implementa una "classe" Annotator che può essere utilizzata per creare automaticamente elementi DIV, posizionarli sotto i testi da annotare e riempire i loro sfondi con immagini SVG. È possibile combinare più DIV per personalizzare ulteriormente le decorazioni. L'approccio è compatibile con più browser, offre flessibilità sul posizionamento degli elementi decorativi e consente un'estensione più semplice con modelli personalizzati.

La libreria è stata sviluppata utilizzando Google Closure Tools perché è modulare e cross-browser, il che aiuta a produrre codice JavaScript compatto e veloce senza alcuna dipendenza aggiuntiva.

Architettura

La libreria è stata progettata come una raccolta di "classi" JavaScript ed espone all'utente tutte le funzionalità necessarie tramite l'annotatore "classe":

libreria di annotatori di testo

Di seguito una breve descrizione delle funzionalità disponibili:

  • annotateDocument - annota gli elementi contrassegnati da un attributo "data-annotate".

  • sottolineare - sottolinea l'elemento

  • evidenziare - mette in evidenza l'elemento

  • strike - elemento strikes

  • sottolineatoSelezionato - sottolinea il testo selezionato

  • highlightSelected - evidenzia il testo selezionato

  • strikeSelected - colpisce il testo selezionato

  • unannotateElement - rimuove l'annotazione dall'elemento

  • getTemplates - restituisce il dizionario dei modelli di annotazione

  • setUnderlineOptions - imposta le impostazioni per l'annotatore di sottolineatura

  • setHighlightOptions - imposta le impostazioni per l'annotatore di evidenziazione

  • setStrikeOptions - imposta le impostazioni per l'annotatore di avvertimento

La classe annotator contiene tre istanze della classe AnnotatorImpl per ciascuna funzione di annotazione: sottolineatura, evidenziazione e barratura.

 tvs.Annotator = function() { this.underliner_ = new tvs.AnnotatorImpl( 'underliner', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.underlinePositioner); this.highlighter_ = new tvs.AnnotatorImpl( 'highlighter', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.highlightPositioner, {opacity: 0.45}); this.striker_ = new tvs.AnnotatorImpl( 'striker', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.strikePositioner); };

Le istanze di AnnotatorImpl vengono create con ID e oggetti di supporto del posizionatore diversi. Gli ID passati vengono utilizzati successivamente nei nomi delle classi CSS e nei nomi dei campi interni, richiedendo che gli ID siano univoci. Inoltre, viene passato un riferimento a un elenco di modelli noti (può essere modificato in seguito).

Ogni oggetto posizionatore è un'implementazione dell'interfaccia IPositioner che ha solo il metodo "getPosition" e ha il seguente aspetto:

 /** * Underline positioner * @implements {tvs.IPositioner} */ tvs.AnnotatorCore.underlinePositioner = /** @type {!tvs.IPositioner} */ ({ /** * @param {Object} elementRect * @param {number} annotationHeight * @return {{left: number, top: number, width: number, height: number}} */ getPosition: function(elementRect, annotationHeight) { return { width: elementRect.width, height: annotationHeight, left: elementRect.left, top: elementRect.bottom - (elementRect.height * 0.1) }; } });

Ciò consente di utilizzare ogni modello con annotazioni di testo sottolineate, evidenziate o barrate. Quando un'annotazione viene applicata a un elemento, il riquadro di delimitazione per l'elemento si ottiene chiamando "getElementRects" come mostrato di seguito:

 var rects = elemOrEv.getClientRects();

Questo metodo restituisce una raccolta di rettangoli che indicano i rettangoli di delimitazione per ogni riquadro in un client. Dopo aver passato ogni rect al posizionatore concreto, otterremo i limiti di destinazione.

Modelli di annotazione di testo SVG

Come accennato in precedenza, esiste un solo set di modelli che vengono utilizzati per tutti i tipi di annotazioni di testo SVG. Ogni modello è costituito da parti del modello. Una parte modello è un'entità che rappresenta il contenuto della parte, la larghezza del modello e la modalità di disegno.

Contenuto

Il contenuto è un insieme di elementi SVG rappresentati come una stringa. Poiché questo contenuto non ha un nodo SVG radice in cui sono impostate la larghezza e l'altezza (in pixel) del viewport, il costruttore della parte del modello li accetta come parametri. Ad esempio, puoi specificare la dimensione di una finestra come 100px x 100px e tracciare una linea su (50, 50) e (25, 25). Dopo aver applicato l'annotazione, tutti gli elementi svg verranno ridimensionati correttamente alla dimensione desiderata. Il valore del contenuto può utilizzare la stringa "{0}" che verrà sostituita con il colore selezionato dall'utente.

Il seguente SVG esegue il rendering di una linea diagonale. Lo useremo come una delle parti in uno stile di annotazione di esempio che segue a breve:

 <line x1="0" y1="0" x2="5" y2="5" stroke-width="2" stroke="red" />

Larghezza

La larghezza del modello è una stringa che può essere "*", "altezza" o qualsiasi altra cosa:

  • “*” imposta la larghezza di tutti gli elementi con una stella uguali tra loro

  • "altezza" imposta la larghezza uguale all'altezza dell'elemento di annotazione

Qualsiasi altra cosa impostata qui verrà impostata direttamente sulle proprietà CSS width e min-width.

proprietà CSS

Modalità Disegna

La modalità Draw è una stringa che può essere "ripetuta" o "allungata". Come indicano i valori, impostandolo su "repeat" si ripeterà il contenuto, mentre impostandolo su "stretch" si allungherà il contenuto.

Ecco un esempio di cosa possiamo ottenere configurando questi tre parametri:

annotazione di testo

L'annotazione di testo nell'esempio sopra contiene 4 parti. La prima parte è la linea diagonale, con la larghezza del modello impostata su "altezza" e la modalità di disegno impostata su "ripeti". La seconda parte ha la larghezza del modello impostata su "*" e la modalità di disegno impostata su "ripeti". La terza parte è impostata per essere larga "15px" e essere disegnata in modalità "ripeti". Infine, la larghezza dell'ultima parte è impostata su "*" e la sua modalità di disegno è impostata su "allunga".

Quando vengono valutate queste larghezze, la prima parte occupa 5 pixel (pari all'altezza dell'elemento di annotazione), la terza parte richiede 15 pixel (come impostato) e lo spazio rimanente viene equamente diviso tra la seconda e la quarta parte.

Quando lo stesso pezzo di testo viene evidenziato utilizzando lo stesso modello, ecco cosa otteniamo:

modalità di disegno

Come puoi vedere, l'altezza dell'elemento di annotazione è maggiore, così come la larghezza della prima parte (poiché la larghezza del modello per quella parte è impostata su "altezza"). Naturalmente, la larghezza della terza parte è rimasta invariata rispetto all'esempio precedente.

L'applicazione di un effetto barrato allo stesso testo con lo stesso modello produce un risultato molto simile al primo. L'unica differenza è la posizione in cui sono posizionati gli elementi di annotazione:

modalità di disegno annotazione del testo

Anche se queste annotazioni di testo sembrano complesse (come appaiono, con quattro parti distinte), usano tutte elementi SVG molto semplici. Come ulteriore esempio, la creazione di una linea ondulata richiede una singola parte, con il seguente semplice contenuto SVG:

 var t = new tvs.Template(new tvs.SvgTemplatePart( '<line y2="16.00" x2="20" y1="4.00" ' + 'x1="10" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>' + '<line y2="4.00" x2="10" y1="16.00" ' + 'x1="0" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>', 20, 20, 'repeat' ))

Quando questi modelli vengono valutati, il contenuto viene ridimensionato e "{0}" viene sostituito automaticamente con il colore specificato. Inoltre, aggiungere nuovi modelli è semplice come aggiungerli a un oggetto JavaScript:

 tvs.AnnotatorDictionary.svgTemplates['brush'] = new tvs.Template(new tvs.SvgTemplatePart( svgContent, 50, 50, '*', 'stretch' ));

Risultati

Ogni annotazione viene applicata aggiungendo alla pagina un elemento div con posizionamento assoluto:

 <div class="tvs-annotate-element"> <div class="tvs-wrap-div"> <table> <tr> <td></td> <td></td> <td></td> </tr> </table> </div> </div>

L'elemento div viene popolato con una tabella in cui ogni cella aggiunta corrisponde a una delle parti nel modello. Il contenuto di ciascuna parte del modello viene aggiunto come URI di dati codificato Base64, con il colore selezionato applicato:

 tvs.SvgTemplatePart.prototype.getBackground = function(color) { var image = tvs.AnnotatorCore.formatString(this.content, [color]); var encodedSVG = goog.crypt.base64.encodeString(image); return 'data:image/svg+xml;base64,' + encodedSVG; };

Incorporamento

Per una migliore esperienza utente, soprattutto quando si tenta di utilizzare questa libreria JavaScript con aree di contenuto modificabili, è importante che Annotatore di testo conosca i limiti del testo attualmente selezionato dall'utente. Rangy, un'accurata libreria JavaScript che si occupa di intervallo e selezione, è stata utilizzata per raggiungere questo obiettivo in modo cross-browser. Rangy fornisce una semplice API basata su standard per eseguire attività di selezione e intervallo DOM comuni in tutti i principali browser, eliminando le diverse implementazioni di questa funzionalità tra Internet Explorer e browser compatibili con DOM. È l'unica dipendenza del progetto.

Una volta incorporato Annotatore di testo, utilizzarlo è un'impresa molto semplice:

 var annotator = new tvs.Annotator(); annotator.underlineSelected();

Ogni elemento annotato è contrassegnato con la classe "tvs-annotated-text" e ogni elemento di annotazione ha la classe "tvs-annotate-element". Rimuovere le annotazioni è ancora più semplice, una riga:

 annotator.unannotateElement(annotatedElement);

Stranezze

Quando la finestra viene ridimensionata, gli elementi possono spostarsi, richiedendo che gli elementi annotati vengano "aggiornati". Questo è gestito dalla biblioteca. Tuttavia; per ridurre l'impatto sulle prestazioni, la chiamata all'aggiornamento delle annotazioni viene ridotta:

 tvs.AnnotatorImpl = function(id, templates, positioner, options) { // ... this.throttle = new goog.Throttle(goog.bind(this.refreshAllAnnotations, this), 50); tvs.AnnotatorCore.registerForWindowResize( this.id,goog.bind(this.throttle.fire, this.throttle)); }; tvs.AnnotatorImpl.prototype.refreshAllAnnotations = function() { var elems = goog.dom.getElementsByClass(this.getCssClassForAnnotated()); var refFunc = goog.bind(this.refreshAnnotation, this); goog.array.forEach(elems, refFunc); };

Dopo l'aggiornamento, gli elementi di annotazione possono essere aggiunti, ridimensionati o rimossi dalla pagina come richiesto.

Convenienza

Per semplificare l'annotazione del testo statico su una pagina, è sufficiente un semplice attributo di dati sull'elemento contenitore:

 data-annotate='underline squiggly green'

Questo annoterà il contenuto dell'elemento con una sottolineatura verde ondulata.

Conclusione

Cos'altro posso dire su questo tutorial di testo SVG? Uno strumento divertente ma potente è stato facilmente implementato. Non credo che trarremmo grandi benefici dall'assicurare il supporto per Internet Explorer 8, poiché potremmo invece finire per complicare l'intera implementazione. Tuttavia, con alcuni miglioramenti e un piccolo lavoro sul nucleo, possiamo estendere la libreria per poter produrre bordi decorativi per elementi non testuali. Inoltre, potrebbe essere un compito interessante implementare alcuni meccanismi per salvare e successivamente ripristinare lo stato del contenuto modificabile di un'annotazione.

Per ora, le possibilità sono limitate solo dalla tua immaginazione (e dalle capacità del browser). Forse vuoi linee di microstampa, sfumature o persino animazioni. Con Annotatore di testo, puoi.