Cara aplikasi pengeditan gambar vektor Boxy SVG menggunakan Local Font Access API agar pengguna dapat memilih font lokal favorit mereka

Local Font Access API menyediakan mekanisme untuk mengakses data font yang diinstal secara lokal oleh pengguna, termasuk detail tingkat tinggi seperti nama, gaya, dan jenis, serta byte mentah dari file font yang mendasarinya. Pelajari cara aplikasi pengeditan SVG, Boxy SVG, menggunakan API ini.

Pengantar

(Artikel ini juga tersedia dalam bentuk video.)

Boxy SVG adalah editor grafik vektor. Kasus penggunaan utamanya adalah mengedit gambar dalam format file SVG, untuk membuat ilustrasi, logo, ikon, dan elemen desain grafis lainnya. Aplikasi ini dikembangkan oleh developer asal Polandia, Jarosław Foksa, dan awalnya dirilis pada 15 Maret 2013. Jarosław mengelola blog Boxy SVG tempat ia mengumumkan fitur baru yang ditambahkan ke aplikasi. Developer ini adalah pendukung kuat Project Fugu Chromium dan bahkan memiliki tag Fugu di pelacak ide aplikasi.

Aplikasi Boxy SVG yang mengedit SVG ikon Project Fugu.

Local Font Access API di Boxy SVG

Satu tambahan fitur yang diblog tentang Jaroslawaw adalah Local Font Access API. Local Font Access API memungkinkan pengguna mengakses font yang diinstal secara lokal, termasuk detail tingkat tinggi seperti nama, gaya, dan jenis, serta byte mentah dari file font yang mendasarinya. Pada screenshot berikut, Anda dapat melihat cara saya memberikan akses aplikasi ke font yang diinstal secara lokal di MacBook dan memilih font Marker Felt untuk teks saya.

Aplikasi Boxy SVG yang mengedit SVG ikon Project Fugu dengan menambahkan teks 'Project Fugu rocks' yang ditetapkan dalam font Marker Felt, yang ditampilkan dipilih di pemilih font.

Kode yang mendasarinya cukup sederhana. Saat pengguna membuka pemilih jenis font untuk pertama kalinya, aplikasi akan memeriksa terlebih dahulu apakah browser web mendukung Local Font Access API.

API ini juga memeriksa versi eksperimental lama API dan menggunakannya jika ada. Mulai tahun 2023, Anda dapat mengabaikan API lama dengan aman karena hanya tersedia dalam waktu singkat melalui tanda Chrome eksperimental, tetapi beberapa turunan Chromium mungkin masih menggunakannya.

let isLocalFontsApiEnabled = (
  // Local Font Access API, Chrome >= 102
  window.queryLocalFonts !== undefined ||
  // Experimental Local Font Access API, Chrome < 102
  navigator.fonts?.query !== undefined
);

Jika Local Font Access API tidak tersedia, pemilih jenis font akan berubah menjadi abu-abu. Teks placeholder akan ditampilkan kepada pengguna, bukan daftar font:

if (isLocalFontsApiEnabled === false) {
  showPlaceholder("no-local-fonts-api");
  return;
}

Pemilih font menampilkan pesan &#39;Browser Anda tidak mendukung Local Font Access API&#39;.

Jika tidak, Local Font Access API akan digunakan untuk mengambil daftar semua font dari sistem operasi. Perhatikan blok try…catch yang diperlukan untuk menangani error izin dengan benar.

let localFonts;

if (isLocalFontsApiEnabled === true) {
  try {
    // Local Font Access API, Chrome >= 102
    if (window.queryLocalFonts) {
      localFonts = await window.queryLocalFonts();
    }
    // Experimental Local Font Access API, Chrome < 102
    else if (navigator.fonts?.query) {
      localFonts = await navigator.fonts.query({
        persistentAccess: true,
      });
    }
  } catch (error) {
    showError(error.message, error.name);
  }
}

Setelah daftar font lokal diambil, fontsIndex yang disederhanakan dan dinormalisasi akan dibuat darinya:

let fontsIndex = [];

for (let localFont of localFonts) {
  let face = "400";

  // Determine the face name
  {
    let subfamily = localFont.style.toLowerCase();
    subfamily = subfamily.replaceAll(" ", "");
    subfamily = subfamily.replaceAll("-", "");
    subfamily = subfamily.replaceAll("_", "");

    if (subfamily.includes("thin")) {
      face = "100";
    } else if (subfamily.includes("extralight")) {
      face = "200";
    } else if (subfamily.includes("light")) {
      face = "300";
    } else if (subfamily.includes("medium")) {
      face = "500";
    } else if (subfamily.includes("semibold")) {
      face = "600";
    } else if (subfamily.includes("extrabold")) {
      face = "800";
    } else if (subfamily.includes("ultrabold")) {
      face = "900";
    } else if (subfamily.includes("bold")) {
      face = "700";
    }

    if (subfamily.includes("italic")) {
      face += "i";
    }
  }

  let descriptor = fontsIndex.find((descriptor) => {
    return descriptor.family === localFont.family);
  });

  if (descriptor) {
    if (descriptor.faces.includes(face) === false) {
      descriptor.faces.push(face);
    }
  } else {
    let descriptor = {
      family: localFont.family,
      faces: [face],
    };

    fontsIndex.push(descriptor);
  }
}

for (let descriptor of fontsIndex) {
  descriptor.faces.sort();
}

Indeks font yang dinormalisasi kemudian disimpan dalam database IndexedDB sehingga mudah dikueri, dibagikan di antara instance aplikasi, dan dipertahankan di antara sesi. Boxy SVG menggunakan Dexie.js untuk mengelola database:

let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);

Bagian Storage Chrome DevTools menampilkan tabel Responden dengan cache font.

Setelah database diisi, widget pemilih font dapat membuat kueri dan menampilkan hasilnya di layar:

Pemilih font diisi dengan font.

Perlu diingat bahwa Boxy SVG merender daftar dalam elemen kustom bernama <bx-fontfamilypicker> dan menata gaya setiap item daftar font sehingga ditampilkan dalam jenis font tertentu. Untuk mengisolasi dari bagian lain halaman, Boxy SVG menggunakan Shadow DOM dalam elemen khusus ini dan elemen khusus lainnya.

Panel Elemen Chrome DevTools yang menampilkan pemilih font yang sedang diperiksa: elemen kustom bernama &#39;bx-fontfamiliypicker&#39;.

Kesimpulan

Fitur font lokal sangat populer, dengan pengguna menikmati akses ke font lokal untuk desain dan kreasi mereka. Saat bentuk API berubah dan fitur terputus sebentar, pengguna akan langsung mengetahui. Jaroslawaw dengan cepat mengubah kode menjadi pola defensif yang dapat dilihat dalam cuplikan di atas yang berfungsi dengan Chrome terbaru dan juga turunan Chromium lainnya yang mungkin belum beralih ke versi terbaru. Coba Boxy SVG dan pastikan untuk memeriksa font yang diinstal secara lokal. Anda mungkin menemukan beberapa font klasik yang sudah lama terlupakan seperti Zapf Dingbats atau Webdings.