چگونه برنامه ویرایش تصویر برداری Boxy SVG از Local Font Access API استفاده می کند تا به کاربران اجازه دهد فونت های محلی مورد علاقه خود را انتخاب کنند

Local Font Access API مکانیزمی برای دسترسی به داده‌های فونت نصب‌شده محلی کاربر، از جمله جزئیات سطح بالاتر مانند نام‌ها، سبک‌ها و خانواده‌ها، و همچنین بایت‌های خام فایل‌های فونت زیرین را فراهم می‌کند. بیاموزید که چگونه برنامه ویرایش SVG Boxy SVG از این API استفاده می کند.

مقدمه

(این مقاله به صورت ویدئویی نیز موجود است.)

Boxy SVG یک ویرایشگر گرافیک برداری است. مورد استفاده اصلی آن ویرایش نقشه ها در قالب فایل SVG برای ایجاد تصاویر، لوگوها، نمادها و سایر عناصر طراحی گرافیکی است. این توسط توسعه دهنده لهستانی Jarosław Foksa توسعه یافته است و در ابتدا در 15 مارس 2013 منتشر شد. Jarosław یک وبلاگ Boxy SVG را اجرا می کند که در آن ویژگی های جدیدی را که به برنامه اضافه می کند را اعلام می کند. توسعه‌دهنده از Project Fugu Chromium حمایت می‌کند و حتی یک برچسب Fugu در ردیاب ایده‌های برنامه دارد.

برنامه Boxy SVG در حال ویرایش نماد Project Fugu SVG.

Local Font Access API در Boxy SVG

یکی از ویژگی های اضافی که Jarosław در مورد آن وبلاگ نویسی کرد، Local Font Access API بود. Local Font Access API به کاربران امکان می دهد به فونت های نصب شده محلی خود، از جمله جزئیات سطح بالاتر مانند نام ها، سبک ها، و خانواده ها و همچنین بایت های خام فایل های فونت زیر دسترسی داشته باشند. در تصویر زیر می توانید ببینید که چگونه به برنامه اجازه دسترسی به فونت های نصب شده محلی در مک بوک خود داده ام و فونت Marker Felt را برای متن خود انتخاب کرده ام.

برنامه Boxy SVG در حال ویرایش نماد Project Fugu SVG با افزودن متن "Project Fugu rocks" در فونت Marker Felt، که در انتخابگر فونت نشان داده شده است.

کد زیربنایی کاملاً ساده است. هنگامی که کاربر برای اولین بار انتخابگر خانواده فونت را باز می کند، برنامه ابتدا بررسی می کند که آیا مرورگر وب از Local Font Access API پشتیبانی می کند یا خیر.

همچنین نسخه آزمایشی قدیمی API را بررسی می کند و در صورت وجود از آن استفاده می کند. از سال 2023، می‌توانید با خیال راحت API قدیمی را نادیده بگیرید زیرا فقط برای مدت کوتاهی از طریق پرچم‌های آزمایشی Chrome در دسترس بود، اما برخی از مشتقات Chromium ممکن است همچنان از آن استفاده کنند.

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

اگر Local Font Access API در دسترس نباشد، انتخابگر خانواده فونت خاکستری می شود. به جای لیست فونت ها، یک متن مکان نگهدار به کاربر نمایش داده می شود:

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

انتخابگر فونت که پیام «مرورگر شما از Local Font Access API پشتیبانی نمی‌کند» را نشان می‌دهد.

در غیر این صورت، Local Font Access API برای بازیابی لیست تمام فونت ها از سیستم عامل استفاده می شود. به بلوک try…catch توجه کنید که برای مدیریت صحیح خطاهای مجوز لازم است.

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

پس از بازیابی لیست فونت های محلی، یک fontsIndex ساده و نرمال شده از آن ایجاد می شود:

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

سپس فهرست فونت های نرمال شده در پایگاه داده IndexedDB ذخیره می شود تا بتوان آن را به راحتی جستجو کرد، بین نمونه های برنامه به اشتراک گذاشت و بین جلسات حفظ کرد. Boxy SVG از Dexie.js برای مدیریت پایگاه داده استفاده می کند:

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

بخش ذخیره‌سازی ابزارهای توسعه‌دهنده Chrome که جدول IndexedDB را با حافظه پنهان فونت‌ها نشان می‌دهد.

هنگامی که پایگاه داده پر شد، ویجت انتخاب فونت می تواند آن را پرس و جو کند و نتایج را روی صفحه نمایش دهد:

انتخابگر فونت پر شده با فونت.

شایان ذکر است که Boxy SVG لیست را در یک عنصر سفارشی به نام <bx-fontfamilypicker> رندر می کند و هر آیتم لیست فونت را به گونه ای سبک می کند که در خانواده فونت خاص نمایش داده شود. برای جداسازی از بقیه صفحه، Boxy SVG از Shadow DOM در این و سایر عناصر سفارشی استفاده می کند.

پانل عناصر Chrome DevTools که انتخابگر فونت در حال بازرسی را نشان می دهد: یک عنصر سفارشی به نام «bx-fontfamiliypicker».

نتیجه گیری

ویژگی فونت های محلی واقعاً محبوب بوده است و کاربران از دسترسی به فونت های محلی خود برای طرح ها و خلاقیت های خود لذت می برند. هنگامی که شکل API تغییر کرد و این ویژگی برای مدت کوتاهی از کار افتاد ، کاربران بلافاصله متوجه شدند. Jarosław سریعاً کد را به الگوی دفاعی تغییر داد که می‌توانید در قطعه بالا مشاهده کنید. Boxy SVG را امتحان کنید و حتما فونت های نصب شده محلی خود را بررسی کنید. ممکن است برخی از آثار کلاسیک فراموش شده مانند Zapf Dingbats یا Webdings را کشف کنید.