SVGcode è un'app web progressiva che ti consente di convertire immagini raster, come JPG, PNG, GIF, WebP, AVIF e così via, in grafiche vettoriali in formato SVG. Utilizza l'API File System Access, l'API Async Clipboard, l'API File handling e la personalizzazione dell'overlay dei controlli delle finestre.
di Gemini Advanced.
Da raster a vettoriale
Hai mai ridimensionato un'immagine e il risultato era pixelato e deludente? Se quindi probabilmente hai usato un formato di immagine raster come WebP, PNG o JPG.
Al contrario, le grafiche vettoriali sono immagini definite da punti in un sistema di coordinate. Questi i punti sono collegati da linee e curve per formare poligoni e altre forme. La grafica vettoriale ha rispetto alle grafiche raster in quanto possono essere ridimensionate o ridotte a qualsiasi risoluzione senza pixelazione.
Introduzione al codice SVG
Ho creato una PWA chiamata SVGcode che può aiutarti a convertire le immagini raster in vettori di rete. Credito a cui è dovuto: non l'ho inventato io. Grazie al codice SVG, mi posiziono sulla uno strumento a riga di comando chiamato Potrace Peter Selinger che ho convertiti in Web Assembly, per poter essere usati in una App web.
![Screenshot dell'applicazione SVGcode.](https://web.dev/static/case-studies/svgcode/image/svgcode-application-scree-7ad5734e2e5e1.png?authuser=0&hl=it)
Utilizzo del codice SVG
Innanzitutto, voglio mostrarti come utilizzare l'app. Inizio con l'immagine teaser per il Chrome Dev Summit che ho scaricato dal canale Twitter ChromiumDev. Questa è un'immagine raster PNG che poi e trascinalo nell'app SVGcode. Quando trascino il file, l'app traccia l'immagine colore per colore, finché non viene visualizzata una versione vettoriale dell'input. Ora posso ingrandire l'immagine e, come puoi vedere, i bordi rimangono nitidi. Ma aumentando lo zoom sul logo di Chrome, puoi notare che il tracciamento non è perfetta, in particolare i contorni del logo sembrano un po' maculati. Posso migliorare il risultato eliminazione delle macchie lunghe fino a cinque pixel.
Posterizzazione nel codice SVG
Un passaggio importante per la vettorializzazione, in particolare per le immagini fotografiche, è la posterizzazione dell'input per ridurre il numero di colori. Il codice SVG mi consente di eseguire questa operazione per ogni canale colore e controllare con il risultato SVG mentre apporto modifiche. Quando il risultato è soddisfacente, posso salvare il file SVG sul mio disco rigido e la uso dove voglio.
API utilizzate nel codice SVG
Ora che hai visto di cosa è capace l'app, vediamo alcune delle API che contribuiscono a che avvenga la magia.
App web progressiva
SVGcode è un'app web progressiva installabile, pertanto è completamente offline. L'app è basata il Modello JS Vanilla per Vite.js e utilizza il popolare plug-in PWA Vite, che crea un service worker che che utilizza Workbox.js in background. Workbox è un insieme di librerie che possono supportare un service worker pronto per la produzione per le app web progressive, questo pattern potrebbe non funzionare necessariamente per tutte le app, ma per il caso d'uso di SVGcode è ottimo.
Overlay controlli finestra
Per massimizzare lo spazio disponibile sullo schermo, il codice SVG usa Personalizzazione dell'overlay dei controlli finestra spostando il menu principale verso l'alto nell'area della barra del titolo. Puoi vedere che questa impostazione viene attivata al termine del flusso di installazione.
API File System Access
Per aprire i file immagine di input e salvare gli SVG risultanti, uso API File System Access. Questo mi consente di tenere un riferimento a ha aperto i file e continuare da dove avevo interrotto, anche dopo aver ricaricato l'app. Ogni volta che un'immagine viene salvato, viene ottimizzato tramite la libreria svgo. L'operazione potrebbe richiedere alcuni istanti. a seconda della complessità del file SVG. Per visualizzare la finestra di dialogo Salva file è necessario un gesto dell'utente. È quindi è importante ottenere l'handle del file prima che venga eseguita l'ottimizzazione SVG, quindi l'utente il gesto non viene invalidato nel momento in cui l'SVG ottimizzato è pronto.
try {
let svg = svgOutput.innerHTML;
let handle = null;
// To not consume the user gesture obtain the handle before preparing the
// blob, which may take longer.
if (supported) {
handle = await showSaveFilePicker({
types: [{description: 'SVG file', accept: {'image/svg+xml': ['.svg']}}],
});
}
showToast(i18n.t('optimizingSVG'), Infinity);
svg = await optimizeSVG(svg);
showToast(i18n.t('savedSVG'));
const blob = new Blob([svg], {type: 'image/svg+xml'});
await fileSave(blob, {description: 'SVG file'}, handle);
} catch (err) {
console.error(err.name, err.message);
showToast(err.message);
}
Trascina
Per aprire un'immagine di input, posso usare la funzione di apertura file o, come avete visto sopra,
trascina un file immagine nell'app. La funzionalità di apertura dei file è piuttosto semplice,
è il caso di trascinamento. L'aspetto particolarmente interessante è che puoi
ottenere un handle di file system dall'elemento Data Transfer tramite
getAsFileSystemHandle()
. Come accennato in precedenza, posso mantenere questo handle in modo che sia pronto quando l'app viene ricaricata.
document.addEventListener('drop', async (event) => {
event.preventDefault();
dropContainer.classList.remove('dropenter');
const item = event.dataTransfer.items[0];
if (item.kind === 'file') {
inputImage.addEventListener(
'load',
() => {
URL.revokeObjectURL(blobURL);
},
{once: true},
);
const handle = await item.getAsFileSystemHandle();
if (handle.kind !== 'file') {
return;
}
const file = await handle.getFile();
const blobURL = URL.createObjectURL(file);
inputImage.src = blobURL;
await set(FILE_HANDLE, handle);
}
});
Per ulteriori dettagli, consulta l'articolo sull'API File System Access e
se ti interessa, studia il codice sorgente del codice SVG in
src/js/filesystem.js
API Async Clipboard
Il codice SVGcode è inoltre completamente integrato negli appunti del sistema operativo tramite l'API Async Clipboard. Puoi incollare nell'app immagini da Esplora file del sistema operativo facendo clic sul incolla immagine o premi Comando o Ctrl più V sulla tastiera.
Di recente, l'API Async Clipboard ha acquisito la capacità di gestire anche le immagini SVG, copia un'immagine SVG e incollala in un'altra applicazione per un'ulteriore elaborazione.
copyButton.addEventListener('click', async () => {
let svg = svgOutput.innerHTML;
showToast(i18n.t('optimizingSVG'), Infinity);
svg = await optimizeSVG(svg);
const textBlob = new Blob([svg], {type: 'text/plain'});
const svgBlob = new Blob([svg], {type: 'image/svg+xml'});
navigator.clipboard.write([
new ClipboardItem({
[svgBlob.type]: svgBlob,
[textBlob.type]: textBlob,
}),
]);
showToast(i18n.t('copiedSVG'));
});
Per scoprire di più, leggi l'articolo Appunti asincroni o esamina il file
src/js/clipboard.js
Gestione di file
Una delle mie funzionalità preferite di SVGcode è la perfetta integrazione con il sistema operativo. Come PWA installato, può diventare un gestore di file, o persino il gestore di file predefinito, per i file immagine. Questo significa che quando mi trovo nel Finder sul mio computer macOS, posso fare clic con il tasto destro del mouse su un'immagine e aprirla con il codice SVG. Questa funzionalità è denominata Gestione file e funziona in base alla proprietà file_handlers nella il file manifest dell'app web e la coda di avvio, che consente all'app di consumare il file passato.
window.launchQueue.setConsumer(async (launchParams) => {
if (!launchParams.files.length) {
return;
}
for (const handle of launchParams.files) {
const file = await handle.getFile();
if (file.type.startsWith('image/')) {
const blobURL = URL.createObjectURL(file);
inputImage.addEventListener(
'load',
() => {
URL.revokeObjectURL(blobURL);
},
{once: true},
);
inputImage.src = blobURL;
await set(FILE_HANDLE, handle);
return;
}
}
});
Per maggiori informazioni, vedi Consentire alle applicazioni web installate di essere gestori di file e visualizzare il codice sorgente in
src/js/filehandling.js
Condivisione web (file)
Un altro esempio di integrazione con il sistema operativo è la funzionalità di condivisione dell'app. Supponendo di volere per apportare modifiche a un file SVG creato con SVGcode, un modo per risolvere il problema è salvare il file, avvia l'app di modifica SVG e apri il file SVG da lì. Un flusso più fluido, però, consiste nel Utilizzare l'API Web Share, che consente di condividere direttamente i file. Quindi se l'app di modifica SVG è una destinazione di condivisione, può ricevere direttamente il file senza deviazioni.
shareSVGButton.addEventListener('click', async () => {
let svg = svgOutput.innerHTML;
svg = await optimizeSVG(svg);
const suggestedFileName =
getSuggestedFileName(await get(FILE_HANDLE)) || 'Untitled.svg';
const file = new File([svg], suggestedFileName, { type: 'image/svg+xml' });
const data = {
files: [file],
};
if (navigator.canShare(data)) {
try {
await navigator.share(data);
} catch (err) {
if (err.name !== 'AbortError') {
console.error(err.name, err.message);
}
}
}
});
Target condivisione web (file)
D'altra parte, il codice SVGcode può anche fungere da destinazione per la condivisione e ricevere file da altre app. A far funzionare questa operazione, l'app deve comunicare al sistema operativo tramite API Web Share Target quali tipi di dati può accettare. Ciò avviene tramite un campo dedicato nel file manifest dell'app web.
{
"share_target": {
"action": "https://svgco.de/share-target/",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"files": [
{
"name": "image",
"accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
}
]
}
}
}
La route action
in realtà non esiste, ma viene gestita esclusivamente nel campo fetch
del service worker
che poi passa i file ricevuti per l'elaborazione effettiva nell'app.
self.addEventListener('fetch', (fetchEvent) => {
if (
fetchEvent.request.url.endsWith('/share-target/') &&
fetchEvent.request.method === 'POST'
) {
return fetchEvent.respondWith(
(async () => {
const formData = await fetchEvent.request.formData();
const image = formData.get('image');
const keys = await caches.keys();
const mediaCache = await caches.open(
keys.filter((key) => key.startsWith('media'))[0],
);
await mediaCache.put('shared-image', new Response(image));
return Response.redirect('./?share-target', 303);
})(),
);
}
});
Conclusione
Abbiamo fatto un rapido tour di alcune delle funzionalità avanzate dell'app nel codice SVG. Spero che questa app può diventare uno strumento essenziale per le tue esigenze di elaborazione delle immagini, insieme ad altre fantastiche app come Squoosh o SVGOMG.
Il codice SVG è disponibile all'indirizzo svgco.de. Hai visto cosa ho fatto lì? Puoi esamina il suo codice sorgente su GitHub. Nota che, poiché Potrace è Licenza concessa da GPL, così come il codice SVG. E con questo, felice vettore! Spero che il codice SVGcode ti sia utile, alcune delle sue funzionalità possono essere fonte di ispirazione per la tua prossima app.
Ringraziamenti
Questo articolo è stato esaminato da Joe Medley.