Puoi controllare come viene disegnata la larghezza del tratto di un SVG?

Attualmente sta sviluppando un’applicazione SVG basata su browser. All’interno di questa app, varie forms possono essere disegnate e posizionate dall’utente, inclusi i rettangoli.

Quando applico una stroke-width ad un elemento rect SVG di dire 1px , il tratto viene applicato all’offset e al riquadro del rect in modi diversi dai diversi browser. Ciò si sta rivelando problematico, soprattutto quando provo a calcolare la larghezza esterna e la posizione visiva di un rettangolo e lo posiziono accanto ad altri elementi.

Per esempio:

  • Firefox aggiunge 1px inserto (in basso e a sinistra) e 1px offset (in alto ea destra)
  • Chrome aggiunge 1 pixel (in alto ea sinistra) e 1 pixel in offset (in basso e a destra)

La mia unica soluzione finora sarebbe stata quella di disegnare i bordi reali (probabilmente con lo strumento path ) e posizionare i bordi dietro l’elemento path . Ma questa soluzione è una soluzione sgradevole, e preferirei non scendere su questa strada se ansible.

Quindi la mia domanda è, puoi controllare come viene disegnata la stroke-width del stroke-width di SVG sugli elementi?

No, non è ansible specificare se il tratto è disegnato all’interno o all’esterno di un elemento. Ho presentato una proposta al gruppo di lavoro SVG per questa funzionalità nel 2003, ma non ha ricevuto alcun supporto (o discussione).

SVG ha proposto l'esempio di traccia-posizione, da phrogz.net/SVG/stroke-location.svg

Come ho notato nella proposta,

  • puoi ottenere lo stesso risultato visivo di “dentro” raddoppiando la larghezza del tratto e quindi utilizzando un tracciato di ritaglio per ritagliare l’object su se stesso, e
  • puoi ottenere lo stesso risultato visivo di “esterno” raddoppiando la larghezza del tratto e sovrapponendo una copia senza fine dell’object sopra di sé.

Modifica : questa risposta potrebbe essere sbagliata in futuro. Dovrebbe essere ansible ottenere questi risultati usando SVG Vector Effects , combinando veStrokePath con veIntersect (per ‘inside’) o con veExclude (per ‘outside’). Tuttavia, Vector Effects è ancora un modulo di bozza funzionante senza implementazioni che posso ancora trovare.

Modifica 2 : la specifica della bozza SVG 2 include una proprietà di stroke-alignment (con i valori possibili al centro | dentro | al di fuori). Alla fine questa proprietà potrebbe trasformarsi in UA.

Modifica 3 : in modo divertente e deludente, il gruppo di lavoro SVG ha rimosso l’ stroke-alignment dei tratti da SVG 2. È ansible vedere alcune delle preoccupazioni descritte dopo la prosa qui .

AGGIORNAMENTO: l’attributo di stroke-alignment stato spostato il 1 ° aprile in una specifica completamente nuova chiamata Strozzi SVG .

A partire dalla bozza dell’Editor SVG 2.0 del 26 febbraio 2015 (e possibilmente dal 13 febbraio ), la proprietà di stroke-alignment del stroke-alignment è presente con i valori inner , center (predefinito) ed outer .

Sembra funzionare allo stesso modo della proprietà della stroke-location del stroke-location proposta da @Phrogz e del successivo suggerimento sulla stroke-position . Questa proprietà è stata pianificata almeno dal 2011, ma a parte un’annotazione che diceva

SVG 2 deve includere un modo per specificare la posizione del tratto

, non è mai stato dettagliato nelle specifiche come è stato differito – fino ad ora, sembra.

Nessun browser supporta questa proprietà, o, per quanto ne so, nessuna delle nuove funzionalità SVG 2, tuttavia, ma speriamo che lo saranno presto. Questa è stata una proprietà che personalmente ho esortato ad avere, e sono davvero felice che sia finalmente lì nelle specifiche.

Sembra che ci siano alcuni problemi su come la proprietà dovrebbe comportarsi su percorsi aperti e loop. Questi problemi, molto probabilmente, prolungheranno le implementazioni attraverso i browser. Tuttavia, aggiornerò questa risposta con nuove informazioni man mano che i browser inizieranno a supportare questa proprietà.

Ho trovato un modo semplice, che ha alcune restrizioni, ma ha funzionato per me:

  • definire la forma in def
  • definire un percorso di clip che faccia riferimento alla forma
  • usalo e raddoppia il tratto con l’esterno tagliato

Ecco un esempio funzionante:

          

Ecco una funzione che calcolerà il numero di pixel che è necessario aggiungere, utilizzando il tratto dato, in alto, a destra, in basso ea sinistra, tutti basati sul browser:

 var getStrokeOffsets = function(stroke){ var strokeFloor = Math.floor(stroke / 2), // max offset strokeCeil = Math.ceil(stroke / 2); // min offset if($.browser.mozilla){ // Mozilla offsets return { bottom: strokeFloor, left: strokeFloor, top: strokeCeil, right: strokeCeil }; }else if($.browser.webkit){ // WebKit offsets return { bottom: strokeCeil, left: strokeFloor, top: strokeFloor, right: strokeCeil }; }else{ // default offsets return { bottom: strokeCeil, left: strokeCeil, top: strokeCeil, right: strokeCeil }; } }; 

Come indicato sopra, dovrai ricalcolare un offset rispetto alle coordinate del tracciato del tratto o raddoppiarne la larghezza e quindi mascherare un lato o l’altro, poiché non solo SVG supporta nativamente l’allineamento del tratto di Illustrator, ma PostScript non lo supporta .

La specifica per i tratti nella seconda edizione di Adobe PostScript Manual afferma: ” 4.5.1 Corsa : l’operatore del tratto disegna una linea di spessore lungo il percorso corrente, per ogni tratto retto o curvo nel tracciato, il tratto disegna una linea centrata su il segmento con lati paralleli al segmento. ” (sottolinea il loro)

Il resto della specifica non ha attributi per compensare la posizione della linea. Quando Illustrator ti consente di allineare all’interno o all’esterno, ricalcola l’offset del percorso effettivo (perché è ancora computazionalmente più economico della sovrastampa e quindi del mascheramento). Le coordinate del percorso nel documento .ai sono di riferimento, non ciò che viene rasterizzato o esportato in un formato finale.

Poiché il formato nativo di Inkscape è SVG spec, non può offrire una funzionalità che manca alla specifica.

Qui è un lavoro intorno per rect bordato interno utilizzando il symbol e l’ use .

Esempio : https://jsbin.com/yopemiwame/edit?html,output

SVG :

     ...   

Nota: assicurarsi di sostituire il ? in use con valori reali.

Background : Il motivo per cui questo funziona è perché il simbolo stabilisce una nuova finestra sostituendo il symbol con svg e creando un elemento nel DOM ombra. Questo svg del DOM ombra viene quindi collegato al tuo elemento SVG corrente. Si noti che svg s può essere annidato e ogni svg crea una nuova finestra, che ritaglia tutto ciò che si sovrappone, incluso il bordo sovrapposto. Per una panoramica molto più dettagliata di cosa sta succedendo leggere questo fantastico articolo di Sara Soueidan.

Una soluzione (sporca) ansible è usando schemi,

ecco un esempio con un triangolo tratteggiato all’interno:

https://jsfiddle.net/qr3p7php/5/

        

Non so quanto sarà utile, ma nel mio caso ho appena creato un altro cerchio con solo il bordo e lo ho collocato “all’interno” dell’altra forma.

È ansible utilizzare i CSS per definire l’ordine di traccia e riempimento. Cioè, prima il tratto e poi il secondo, e ottieni l’effetto desiderato.

MDN su paint-order : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-order

Codice CSS:

 paint-order: stroke;