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 pengguna yang diinstal secara lokal, termasuk detail pada tingkat yang lebih tinggi seperti nama, gaya, dan kelompok, 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 pengembang Polandia Jarosław Foksa dan awalnya dirilis pada 15 Maret 2013. Jarosław menjalankan blog SVG Boxy tempat ia mengumumkan fitur baru yang ditambahkan ke aplikasinya. Developer tersebut sangat mendukung Project Fugu Chromium dan bahkan memiliki tag Fugu di pelacak ide aplikasi.

Aplikasi Boxy SVG yang mengedit ikon SVG Project Fugu.

Local Font Access API di Boxy SVG

Salah satu fitur tambahan yang di-blog-nya Jarosław adalah Local Font Access API. Local Font Access API memungkinkan pengguna mengakses font yang diinstal secara lokal, termasuk detail pada tingkat yang lebih tinggi seperti nama, gaya, dan kelompok, serta byte mentah dari file font yang mendasarinya. Dalam screenshot berikut, Anda dapat melihat cara saya memberikan akses aplikasi ke font yang diinstal secara lokal di MacBook saya dan memilih font Marker Felt untuk teks saya.

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

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

Alat ini juga memeriksa API versi eksperimental lama dan menggunakannya jika ada. Mulai tahun 2023, Anda dapat mengabaikan API lama dengan aman karena API tersebut hanya tersedia untuk waktu yang 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 dinormalkan akan dibuat dari daftar tersebut:

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 telah dinormalkan kemudian disimpan dalam database IndexedDB sehingga dapat dikueri dengan mudah, dibagikan di antara instance aplikasi, dan dipertahankan di antara sesi. SVG Boxy 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 Chrome DevTools Storage menampilkan tabel IndexedDB dengan cache font.

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

Pemilih font diisi dengan font.

Perlu diketahui 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 halaman lainnya, Boxy SVG menggunakan Shadow DOM dalam elemen kustom ini dan elemen kustom lainnya.

Panel Elemen Chrome DevTools menunjukkan pemilih font yang sedang diperiksa: elemen khusus bernama &#39;bx-fontfamiliy picker&#39;.

Kesimpulan

Fitur font lokal sangat populer, dan pengguna menikmati akses ke font lokal untuk desain dan kreasi mereka. Saat bentuk API berubah dan fitur rusak sebentar, pengguna akan segera mencatatnya. Jarosław 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 dialihkan ke versi terbaru. Coba Boxy SVG dan pastikan untuk memeriksa font yang diinstal secara lokal. Anda mungkin menemukan beberapa game klasik yang sudah lama terlupakan seperti Zapf Dingbats atau Webdings.