Cách ứng dụng chỉnh sửa hình ảnh vectơ Boxy SVG sử dụng API Local Font Access để cho phép người dùng chọn phông chữ trên máy yêu thích của họ

API truy cập phông chữ cục bộ cung cấp cơ chế truy cập dữ liệu phông chữ được cài đặt cục bộ của người dùng, bao gồm các chi tiết cấp cao hơn như tên, kiểu và họ, cũng như byte thô của tệp phông chữ cơ bản. Tìm hiểu cách ứng dụng chỉnh sửa SVG Boxy SVG sử dụng API này.

Giới thiệu

(Bài viết này cũng có sẵn ở dạng video.)

Boxy SVG là trình chỉnh sửa đồ hoạ vectơ. Trường hợp sử dụng chính là chỉnh sửa các bản vẽ ở định dạng tệp SVG để tạo hình minh hoạ, biểu trưng, biểu tượng và các thành phần khác của thiết kế đồ hoạ. Trò chơi này do nhà phát triển Ba Lan Jaros Camera Foksa phát triển và phát hành lần đầu vào ngày 15 tháng 3 năm 2013. Jaroslevaw điều hành một blog Boxy SVG để thông báo về các tính năng mới mà anh thêm vào ứng dụng. Nhà phát triển này rất ủng hộ Project Fugu của Chromium và thậm chí còn gắn thẻ Fugu trên công cụ theo dõi ý tưởng của ứng dụng.

Ứng dụng Boxy SVG chỉnh sửa đồ hoạ SVG (Đồ hoạ vectơ có thể mở rộng) cho biểu tượng Project Fugu.

API truy cập phông chữ cục bộ trong Boxy SVG

Một tính năng bổ sung mà Jarosowski đã đăng trên blogLocal Font Access API (API Truy cập phông chữ cục bộ). API truy cập phông chữ cục bộ cho phép người dùng truy cập phông chữ được cài đặt trên máy, bao gồm cả các chi tiết cấp cao hơn như tên, kiểu và họ, cũng như các byte thô của tệp phông chữ cơ bản. Trong ảnh chụp màn hình sau đây, bạn có thể thấy cách tôi cấp cho ứng dụng quyền truy cập vào các phông chữ được cài đặt cục bộ trên MacBook và chọn phông chữ Marker Felt cho văn bản của mình.

Ứng dụng Boxy SVG chỉnh sửa SVG (Đồ hoạ vectơ có thể mở rộng) của biểu tượng Project Fugu, thêm văn bản "Project Fugu rock" (Dự án Fugu đá) trong phông chữ Marker Felt, xuất hiện khi được chọn trong bộ chọn phông chữ.

Mã cơ bản khá đơn giản. Khi người dùng mở bộ chọn bộ phông chữ lần đầu tiên, trước tiên, ứng dụng sẽ kiểm tra xem trình duyệt web có hỗ trợ API truy cập phông chữ cục bộ hay không.

Tính năng này cũng kiểm tra phiên bản thử nghiệm cũ của API và sử dụng phiên bản đó nếu có. Kể từ năm 2023, bạn có thể yên tâm bỏ qua API cũ vì API này chỉ hoạt động trong một thời gian ngắn thông qua các cờ Chrome thử nghiệm. Tuy nhiên, một số công cụ phái sinh của Chromium vẫn có thể sử dụng API này.

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

Nếu API truy cập phông chữ cục bộ không có sẵn, bộ chọn bộ phông chữ sẽ chuyển sang màu xám. Người dùng sẽ thấy một văn bản giữ chỗ thay cho danh sách phông chữ:

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

Bộ chọn phông chữ hiển thị thông báo &quot;Trình duyệt của bạn không hỗ trợ API truy cập phông chữ cục bộ&quot;.

Nếu không, API truy cập phông chữ cục bộ sẽ được dùng để truy xuất danh sách tất cả phông chữ từ hệ điều hành. Hãy lưu ý khối try…catch cần thiết để xử lý các lỗi về quyền đúng cách.

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

Sau khi truy xuất danh sách phông chữ trên máy, hệ thống sẽ tạo một fontsIndex đơn giản và đã chuẩn hoá từ đó:

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

Sau đó, chỉ mục phông chữ đã chuẩn hoá được lưu trữ trong cơ sở dữ liệu IndexedDB để có thể dễ dàng truy vấn, chia sẻ giữa các thực thể ứng dụng và lưu giữ giữa các phiên. Boxy SVG sử dụng Dexie.js để quản lý cơ sở dữ liệu:

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

Phần Bộ nhớ Công cụ của Chrome cho nhà phát triển hiển thị bảng IndexedDB cùng với bộ nhớ đệm phông chữ.

Sau khi cơ sở dữ liệu được điền sẵn, tiện ích bộ chọn phông chữ có thể truy vấn cơ sở dữ liệu đó và cho thấy kết quả trên màn hình:

Bộ chọn phông chữ được điền sẵn phông chữ.

Điều đáng nói đến là Boxy SVG hiển thị danh sách trong một phần tử tuỳ chỉnh có tên là <bx-fontfamilypicker> và tạo kiểu cho từng mục trong danh sách phông chữ để nó xuất hiện trong bộ phông chữ cụ thể. Để tách biệt với phần còn lại của trang, Boxy SVG sử dụng Shadow DOM trong phần tử này và các phần tử tuỳ chỉnh khác.

Bảng điều khiển Phần tử của Công cụ của Chrome cho nhà phát triển hiển thị bộ chọn phông chữ đang được kiểm tra: một phần tử tuỳ chỉnh có tên là &quot;bx-fontfamiliypicker&quot;.

Kết luận

Tính năng phông chữ trên máy thực sự phổ biến, khi người dùng thích sử dụng phông chữ trên máy để thiết kế và sáng tạo. Khi hình dạng API thay đổi và tính năng bị lỗi trong thời gian ngắn, người dùng sẽ ghi chú ngay lập tức. Jarosowski đã nhanh chóng thay đổi mã này thành mô hình phòng thủ mà bạn có thể thấy trong đoạn mã ở trên. Mô hình này hoạt động với Chrome phiên bản mới nhất cũng như các cấu trúc phái sinh khác của Chromium có thể chưa được chuyển sang phiên bản mới nhất. Hãy thử sử dụng SVG Boxy và nhớ kiểm tra các phông chữ được cài đặt cục bộ của bạn. Bạn có thể khám phá một số tác phẩm kinh điển đã bị lãng quên từ lâu như Zapf Dingbats hoặc Webdings.