2012-10-04 9 views
11

Ho un progetto da molto tempo: uno strumento di grafica vettoriale di base che gira nel browser e usa SVG e Javascript (forse ne hai visto alcuni altrove). Lo strumento ha solo un insieme molto limitato di funzioni, perché il pubblico è limitato e lo scopo è molto specifico e in effetti non è possibile che vi siano altre funzionalità rispetto a ciò che è esplicitamente consentito (lo sai). Una caratteristica mancante è l'erosione (nota anche come inset o thin) e la dilatazione (inizio, addensamento, grassetto) dei poligoni e altri elementi grafici.Come posso implementare Offset Path Effect in SVG senza usare Javascript o dilatare/erodere i filtri?

Ho usato Offset Path Effect di Adobe Illustrator molte volte e con esso posso facilmente fare copie di oggetti grafici che sono assottigliati o addensati, senza intaccare l'oggetto originale, che quindi può essere praticamente qualsiasi cosa supportata dal programma.

Ho provato a ottenere la stessa funzionalità per funzionare in SVG, ma senza successo.

Ho provato quanto segue:
- dilatarsi e erodere filtri, ma con risultati non soddisfacenti (please see the image here)
- biblioteca Shapely di Python lato server, ma questa soluzione è troppo lento e permette solo la nicchia o fin dall'inizio poligoni di base (description here)
- per trovare javascript/code/funzione di libreria, che potrebbero alterare i dati del percorso di elementi grafici, ma ha trovato nulla per javascript

Quindi esiste un modo significativo per implementare questa come percorso di effetto offset e Come?

+1

Vedi anche [questo articolo] (https://hal.inria.fr/inria-00518005/documento) –

risposta

19

Questa è una risposta "rispondi alla tua domanda - share your knowledge, Q&A-style", ma se hai una risposta migliore, utilizza liberamente la tastiera.

Ho usato SO solo per pochi giorni, quindi per favore non mandatemi a valle. Ho ottenuto un interessante workaround idea a questo problema, che si basa su tratti e maschere a larghezza variabile.

Ma iniziamo dalla tua (o mia) prima idea. Quando andremo a erodere (sottili) oggetti grafici in SVG, il primo pensiero ovvio è di usare il filtro di erosione:

Ma poiché il filtro di erosione (e anche la dilatazione) uses pixel data (the rasterized path) il risultato non è bello in tutti i casi. In effetti, non ho mai visto una bella erosione quando ho usato per filtrare oggetti vettoriali. Vedere il cappello e la bocca:

Eroded image

Il filtro si dilatano ha problemi simili (il naso non è bello e il berretto da baseball è sconnesso e alcune altre incongruenze):

Dilated image

Tutti gli utenti di Adobe Illustrator conoscono gli effetti del percorso, che possono essere utilizzati per applicare varie operazioni di tracciamento a forme (oggetti). Questi effetti non cambiano i dati del percorso originale, ma creano solo una copia modificata dell'oggetto. Uno dei più utilizzabili è Offset Path Effect, che può essere utilizzato per partire dall'oggetto selezionato di una distanza specificata (o qualcosa di simile). SVG: s erode e dilatare i filtri hanno delle somiglianze con Illustrator Offset Path Effect, ma la qualità è come una operazione vettoriale (contro bitmap) alta.

Il formato SVG al suo stato attuale, manca del supporto per Offset Path simile a Illustrator, ma è possibile ottenere la stessa funzionalità utilizzando tratti e maschere a larghezza variabile come indicato in here.

Immergiti nel mondo delle maschere SVG. È possibile ottenere la dilatazione (o il percorso finale o addensare) semplicemente aumentando la larghezza del tratto, ma l'erosione (o il percorso interno o il diradamento) necessita di qualcosa di più, ad esempio le maschere. In SVG, qualsiasi oggetto grafico o elemento 'g' può essere utilizzato come maschera alfa per comporre l'oggetto corrente sullo sfondo (W3C SVG 1.1 Recommendation).

Quanto sopra significa che non solo il riempimento dell'oggetto può essere utilizzato come maschera, ma anche un tratto. E regolando la larghezza del tratto del percorso che viene utilizzato come maschera, è possibile controllare la quantità dell'oggetto corrente (in cui la maschera viene applicata utilizzando l'attributo mask) è mascherata.

Vediamo un esempio di utilizzo della maschera. Prima definiamo un percorso in SVG: s defs elemento:

<defs> 
<path id="head_path" d="M133.833,139.777c1 ...clip... 139.777z"/> 
</defs> 

Quando definiamo un percorso in elemento defs, si elimina la necessità di ripetere gli stessi dati in altre parti del documento. L'attributo id del percorso viene utilizzato per fare riferimento al percorso da alcuni punti del documento.

Ora possiamo usare questi dati di percorso in maschera:

<defs> 
... 
<mask id="myMask" maskUnits="userSpaceOnUse"> 
<use xlink:href="#head_path" fill="#FFFFFF" stroke="#000000" 
stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/> 
</mask> 
... 
</defs> 

I riferimenti elemento 'uso' per l'elemento 'percorso', il cui ID è 'head_path' e indica che il contenuto grafico (in questo caso solo i dati del percorso) dell'elemento 'head_path' sono inclusi in questa maschera. La larghezza del tratto definita nell'elemento "uso" sopra riportato sarà la quantità dell'effetto offset (erode). Questo importo è mascherato dall'elemento nel caso, che verrà disegnato successivamente.

Okay, disegnare prima la 'testa' senza mascherare per vedere quanto è bello:

... 
</defs> 
<use x="5" y="5" xlink:href="#head_path" fill="#4477FF" stroke="black" 
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> 

Questo produce il seguente forma:

Original shape

Ora prova, quello che possiamo raggiungere utilizzando la maschera:

... 
</defs> 
<use x="5" y="5" xlink:href="#head_path" fill="#22EE22" stroke="black" 
stroke-width="21" stroke-linecap="round" stroke-linejoin="round" 
mask="url(#myMask)"/> 

Il suddetto elemento 'uso' i Viene richiesto di usare "myMask" come maschera e "head_path" come contenuto grafico. L'effetto maschera viene applicata all'elemento 'uso' e la seguente forma viene disegnata:

Masked shape

Se impilare sia sulla parte superiore di ciascuno, possiamo confrontare la testa originale alla testa mascherata:

Original and masked shape

Non male? Mettiamo a confronto il primo tentativo utilizzando SVG erodere versione filtrata alla versione mascherata:

Eroded vs masked

Quello di sinistra è erodere-filtrato e quello di destra è mascherato da imitare Illustrator-come percorso di effetto Offset. Nessun artefatto strano nel cappello e nella bocca!

Che ne dici di dilatare?C'è un modo per rimuovere il path unfidelity sul naso e la scrappiness del berretto da baseball? Sicuro. E il metodo è davvero semplice ma una specie di hack. Fortunatamente non è necessario usare maschere. Invece possiamo regolare la larghezza del tratto per ottenere l'effetto desiderato. E poiché il tratto è già utilizzato per l'audacia, per ottenere un tratto nero attorno a una forma audace (se mai desiderato), dobbiamo aggiungere una copia aggiuntiva dell'elemento con un tratto più ampio e disporlo sotto la forma in grassetto:

<!-- To get the black stroke --> 
<use x="220" y="5" xlink:href="#head_path" fill="red" stroke="black" 
stroke-width="24" stroke-linecap="round" stroke-linejoin="round"/> 
<!-- To get the boldened shape --> 
<use x="220" y="5" xlink:href="#head_path" fill="red" stroke="red" 
stroke-width="21" stroke-linecap="round" stroke-linejoin="round"/> 

Questo produce il seguente forma:

Offset Path Effect applied

Qui sia la forma originale e quello con la nostra abitudine Path Offset effetto applicato:

Original and Offset Path Effect applied

Come nostra consuetudine boldening paragona a dilatare filtro:

Dilated vs Boldened

Quello di sinistra (sopra) è dilatato con SVG: s dilatano filtro, quello di destra è boldened utilizzando il nostro personalizzato Offset percorso di effetto. Carino, mi piace Percorso segue fedelmente il percorso originale alla distanza data e nessun segno di scrappiness sul berretto da baseball.

Infine diamo tirare tutti i fili insieme: Dilate/Origina/Erode vs Offset Path Combined

Il sinistro (sopra) utilizza dilatare/erodere filtro SVG e quello di destra usa Illustrator imitato Effetto Scostamento tracciato, che si ottiene utilizzando maschera SVG e colpi più spessi. Quale sceglieresti?

Conclusione: Non siamo obbligati a utilizzare Javascript o altri script per addensare o assottigliare elementi grafici in SVG. I filtri Erode e Dilate di SVG possono avere alcuni scopi, ma non sono adatti per "modifiche" di percorso di alta qualità. Le maschere sono un po 'complicate da usare, ma dopo alcuni esperimenti ci si familiarizza con esse. Spero davvero che SVG in futuro supporti l'Offset Path Effect in modo nativo, senza utilizzare questo tipo di hack.

ho jsfiddled le forme utilizzate in questi esempi per voi a giocare con i filtri e maschere: http://jsfiddle.net/7Y4am/
(! Prova almeno a cambiare le larghezze ictus)

(Scusate il mio pessimo inglese, che ottiene madrelingua per ridere fino alla morte, ma per favore ricorda, appartengo al 94% dell'umanità, che non parla inglese in modo nativo, ma per fortuna abbiamo Google Translate.)

+0

Ho aggiunto un esempio di testo con Offset Path Effect: http://jsfiddle.net/BbYV6/. Dobbiamo usare maskUnits = "objectBoundingBox" invece di maskUnits = "userSpaceOnUse" per portare la maschera nel posto giusto. E potremmo preferire stroke-linejoin = "mitre" invece di stroke-linejoin = "round". E sfortunatamente a causa della mancanza di kerning-on-the-fly, il kerning è ciò che il browser vuole. Se hai idee, condividili: http://stackoverflow.com/questions/12654826/kerning-on-the-fly. –

+0

La cosa stupida è che SVG utilizza un elemento di struttura rettangolare per le operazioni morfologiche. Le persone probabilmente vogliono quelle rotonde. – nraynaud

+1

http://sourceforge.net/p/jsclipper/wiki/Home/ Ho appena scoperto che – nraynaud

Problemi correlati