SVGcode: aplikacja PWA do konwertowania obrazów rastrowych na grafiki wektorowe SVG.

SVGcode to progresywna aplikacja internetowa, która umożliwia konwertowanie obrazów rastrowych, takich jak JPG, PNG, GIF, WebP, AVIF itp., na grafiki wektorowe w formacie SVG. Wykorzystywane są interfejsy File System Access API, Async Clipboard API, File handling API i Window Controls Overlay.

.
Jeśli wolisz oglądać ten materiał, a nie go czytać, ten artykuł jest dostępny również jako film.

Od rastrowania do wektora

Czy zdarzyło Ci się przeskalować obraz, który był rozpikselowany i nie był zadowalający? Jeśli więc prawdopodobnie korzystasz z formatu rastrowego, takiego jak WebP, PNG czy JPG.

Skalowanie obrazu rastrowego powoduje, że jest on rozpikselowany.

Grafika wektorowa to natomiast obrazy zdefiniowane za pomocą punktów w układzie współrzędnych. Te punkty są połączone liniami i krzywymi, tworząc wielokąty i inne kształty. Grafika wektorowa ma mają przewagę nad grafiką rastrową, ponieważ można je skalować w górę lub w dół do dowolnej rozdzielczości. bez pikselizacji.

Skalowanie obrazu wektorowego bez utraty jakości.

Przedstawiamy SVGcode

Mam aplikację PWA o nazwie SVGcode, która pomaga konwertować obrazy rastrowe na wektory dystrybucyjne. Kredyt, na który należy zwrócić środki: to nie ja wymyśliłem(-am). Dzięki SVGcode narzędzia wiersza poleceń Potrace, Peter Selinger, przekonwertowano na Web Assembly, więc można go używać Aplikacja internetowa.

Zrzut ekranu aplikacji SVGcode.
Aplikacja SVGcode.
.

Korzystanie z kodu SVG

Najpierw pokażę, jak korzystać z tej aplikacji. Zaczynam od zwiastuna Chrome Dev Summit pobranego z kanału ChromiumDev na Twitterze. To jest rastrowy obraz PNG, i przeciągnij je do aplikacji SVGcode. Gdy upuszczam plik, aplikacja śledzi kolor obrazu według koloru, aż pojawi się wektorowa wersja danych wejściowych. Mogę teraz powiększyć obraz i widzę, więc krawędzie pozostają ostre. Po zbliżeniu logo Chrome widać, że śledzenie Zwłaszcza kontury logo są nieco niewyraźne. Mogę poprawić wynik, usuwania plamek śledzenia przez usunięcie plamek o długości do 5 pikseli.

Konwertuję upuszczony obraz do SVG.

Posteryzacja w kodzie SVG

Ważnym krokiem w procesie wektoryzacji, zwłaszcza w przypadku zdjęć fotograficznych, jest przeniesienie danych wejściowych w postaci plakatu. obrazu, aby zmniejszyć liczbę kolorów. SVG pozwala mi to zrobić z każdym kanałem kolorów. gdy wprowadzam zmiany w pliku SVG. Jeśli wynik jest zadowalający, mogę zapisać plik SVG na dysku twardym i używać jej, gdzie tylko chcę.

Zmniejszanie liczby kolorów na plakatach na obrazie.

Interfejsy API używane w SVGcode

Skoro już wiesz, jakie możliwości daje aplikacja, czas opowiedzieć o kilku interfejsach API, dzięki którym magia.

Progresywna aplikacja internetowa

SVGcode to instalowana progresywna aplikacja internetowa, która jest w pełni obsługiwana w trybie offline. Aplikacja jest oparta w Szablon Vanilla JS dla Vite.js i korzysta z popularnego Wtyczka Vite PWA tworząca skrypt service worker, korzysta z Workbox.js. Workbox to zestaw które mogą obsługiwać gotowe do produkcji skrypt service worker dla progresywnych aplikacji internetowych. Ten wzorzec może nie działać we wszystkich aplikacjach, ale w przypadku SVGkod jest bardzo przydatny.

Nakładka z elementami sterującymi okna

Aby zmaksymalizować ilość dostępnego miejsca na ekranie, SVG używa funkcji Dostosowanie nakładki z elementami sterującymi okien przez przeniesienie jej menu głównego w górę do w obszarze paska tytułu. Aktywacja jest widoczna na końcu procesu instalacji.

Zainstalowanie kodu SVG i aktywowanie dostosowania nakładki elementów sterujących okien

File System Access API

Aby otworzyć pliki obrazów wejściowych i zapisać powstałe w ten sposób obrazy SVG, Interfejs File System Access API Dzięki temu mogę zachować odniesienie do otwieranych plików i kontynuuje od tego samego miejsca, nawet po ponownym załadowaniu aplikacji. Za każdym razem, gdy zdjęcie zostanie zapisane, jest optymalizowane za pomocą biblioteki svgo, co może chwilę potrwać. w zależności od złożoności pliku SVG. Aby wyświetlić okno zapisywania pliku, użytkownik musi wykonać gest. Jest Dlatego ważne jest uzyskanie uchwytu pliku przed optymalizacją SVG, nie jest unieważniony, gdy zoptymalizowane SVG będzie gotowe.

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);
}

Przeciągnij i upuść

Do otwarcia obrazu wejściowego mogę użyć funkcji otwierania pliku lub, jak widać powyżej, przeciągnij plik graficzny i upuść go w aplikacji. Funkcja otwierania plików jest dość prosta, to „przeciągnij i upuść”. Szczególną zaletą tego rozwiązania jest możliwość pobierz uchwyt systemu plików z elementu przenoszenia danych za pomocą getAsFileSystemHandle() . Jak już wspomnieliśmy, mogę zachować ten nick, aby był gotowy, gdy aplikacja zostanie ponownie załadowana.

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);
  }
});

Aby dowiedzieć się więcej, zapoznaj się z artykułem o interfejsie File System Access API oraz Jeżeli chcesz, możesz zapoznać się z kodem źródłowym SVG src/js/filesystem.js.

Async Clipboard API

Format SVG jest też w pełni zintegrowany ze schowkiem systemu operacyjnego za pomocą interfejsu Async Clipboard API. Obrazy z eksploratora plików systemu operacyjnego możesz wkleić do aplikacji, klikając wklej obraz albo naciśnij Command lub Control + V na klawiaturze.

Wklejanie obrazu z eksploratora plików do SVG.

Interfejs Async Clipboard API niedawno uzyskał możliwość obsługi obrazów SVG, a także skopiować obraz SVG i wkleić go do innej aplikacji do dalszego przetwarzania.

Kopiowanie obrazu z kodu SVG do SVGOMG.
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'));
});

Aby dowiedzieć się więcej, przeczytaj artykuł Schowek asynchroniczny lub zapoznaj się z plikiem src/js/clipboard.js.

Obsługa plików

Jedną z moich ulubionych cech SVGcode jest to, że dobrze komponuje się z systemem operacyjnym. Jako może stać się modułem do obsługi plików graficznych, a nawet domyślnym modułem obsługi plików. Ten Oznacza to, że gdy jestem w Finderze na komputerze z macOS, mogę kliknąć obraz prawym przyciskiem myszy i otworzyć go SVG. Ta funkcja nazywa się „Obsługa plików” i działa na podstawie właściwości file_handlers w Plik manifestu aplikacji internetowej i kolejka uruchamiania, które pozwalają aplikacji na przetworzenie przekazywanego pliku.

Otwieram plik na pulpicie z zainstalowaną aplikacją SVGcode.
.
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;
    }
  }
});

Więcej informacji znajdziesz w sekcji Zezwalanie zainstalowanym aplikacjom internetowym na moduły obsługi plików i wyświetlaniu kodu źródłowego w src/js/filehandling.js.

Udostępnianie w internecie (pliki)

Innym przykładem dostosowania aplikacji do systemu operacyjnego jest dostępna w niej funkcja udostępniania. Zakładając, że chcę edycji w pliku SVG utworzonego za pomocą kodu SVG. Jednym ze sposobów na to jest zapisanie pliku, uruchom aplikację do edycji SVG i otwórz tam plik SVG. Płynniejsza konfiguracja to korzystać z interfejsu Web Share API, który umożliwia bezpośrednie udostępnianie plików. Jeśli więc Aplikacja do edycji SVG jest celem udostępniania, może bezpośrednio odbierać plik bez odchylenia.

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);
      }
    }
  }
});
.
, Udostępnianie obrazu SVG w Gmailu.

Cel udostępniania w internecie (pliki)

Z kolei kod SVG może też działać jako element docelowy udostępniania i odbierać pliki z innych aplikacji. Do aplikacja musi powiadomić o tym system operacyjny Web Share Target API rodzaje danych, które akceptuje. Odbywa się to przez specjalne pole w pliku manifestu aplikacji internetowej.

{
  "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"]
        }
      ]
    }
  }
}

Trasa action tak naprawdę nie istnieje, ale jest obsługiwana czysto w fetch skryptu service worker który następnie przekazuje odebrane pliki do przetworzenia w aplikacji.

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);
      })(),
    );
  }
});
.
, Udostępniam zrzut ekranu w SVGcode.

Podsumowanie

Dobrze, oto krótka prezentacja o niektórych zaawansowanych funkcjach aplikacji SVG. Mam nadzieję, że ta aplikacja może stać się podstawowym narzędziem do przetwarzania obrazów, podobnie jak inne niesamowite aplikacje, takie jak Squoosh lub SVGOMG.

Kod SVG znajdziesz na svgco.de. Zobaczymy, co tam robiłem. Dostępne opcje sprawdź jego kod źródłowy na GitHubie. Skoro Potrace jest Podobnie jest z kodem SVG. Życzymy udanej wektoryzacji. Mam nadzieję, że SVG będzie przydatny. Niektóre z jego funkcji mogą być inspiracją dla Twojej kolejnej aplikacji.

Podziękowania

Ten artykuł został zrecenzowany przez Joe Medley.