Chrome 103支持使用本地字體,純前端導出PDF優化

在前端導出PDF,解決中文亂碼一直是一個頭疼的問題。要解決這個問題,需要將ttf等字體文件內容註冊到頁面PDF生成器中。但是之前網頁是沒有權限直接獲取客戶機器字體文件,這時就需要從服務器下載字體文件或者提示用戶選擇字體文件上傳到頁面。對於動輒數十兆(M)的中文字體文件,網絡不好時並不是一個好的解決方案。

Chrome 103

提高頁面性能的一種方法是對當前的使用資源經行提示。例如,預加載文件或連接到不同的服務器。

<link as="font" crossorigin="anonymous"
      href="..." rel="preload">
<link as="font" crossorigin="anonymous"
      href="..." rel="preload">
<link href="https://web-dev.imgix.net"
      rel="preconnect">

但是在服務器發送頁面內容之前,瀏覽器是無法對提示採取行動。

服務器需要幾百毫秒才能生成一個請求頁面,在瀏覽器開始接收頁面內容之前,服務器是不進行任何處理的。但是在這個等待的過程中,服務器是需要一些固定子資源,例如 CSS 文件、JavaScript 和圖像內容,這個時候服務器可以立即響應新的 HTTP 103 Early Hints 狀態代碼,並詢問瀏覽器預加載那些子資源,以提供高座效率。

一旦服務器生成了頁面,它就可以用正常的 HTTP 200 響應發送它。當頁面進入時,瀏覽器已經開始加載所需的資源。作爲一個新 HTTP 狀態代碼,所以它需要更新我們服務器。

本地字體訪問

Web 上的字體一直是一個挑戰,尤其是允許用戶創建自己的圖形和設計的應用程序就是一個難點。現在應用程序只能使用網絡字體,但無法獲得用戶在其計算機上安裝的字體列表;而且,無法訪問完整的字體表數據,如果我們需要實現自己的自定義文本堆棧,就很複雜。

而在新版本中,這個問題得到了很好解決。Chrome 103版本中新的字體API可以讓web應用獲取到用戶在本地電腦上安裝的所有字體信息,同時還可以獲取到字體內容。

調用window.queryLocalFonts(),會返回用戶安裝字體的數組。

const pickedFonts = await self.queryLocalFonts();
for (const fontData of pickedFonts) {
  console.log(fontData.postscriptName);
  console.log(fontData.fullName);
  console.log(fontData.family);
  console.log(fontData.style);
}

處於安全性的考慮,獲取字體信息需要獲取到用戶的授權。當第一調用queryLocalFonts時,Chrome會彈出權限申請:

權限同意後,就可以獲取所有安裝字體的信息

使用navigator.permissions.query可以檢查權限

async function requestPremission(){
  const { state } = await navigator.permissions.query({
    name: "local-fonts"
  });
  console.log(state)
  if (state === 'granted') {
    query();
  } else if (state === 'prompt') {
    alert("請授予權限!")
    query();
  }
  else{
    alert("沒有權限獲取字體")
  }
}

使用本地字體導出PDF

接下來我們介紹如何使用本地字體進行PDF導出。
選擇需要使用的字體內容,註冊到PDF生成工具中

使用blob 方法可以獲取字體文件內容
let currentFont = fontList[fontListSelect.value];
const blob = await currentFont.blob();

使用字體名稱註冊

//將Blob 對象轉換成 ArrayBuffer
var reader = new FileReader();
reader.onload = function (e) {
  var fontrrayBuffer = reader.result;
  var fonts = GC.Spread.Sheets.PDF.PDFFontsManager.getFont(currentFont.family) || {};
  fonts[fontType] = fontrrayBuffer;
  GC.Spread.Sheets.PDF.PDFFontsManager.registerFont(currentFont.family, fonts);
}
reader.readAsArrayBuffer(blob);

接下來導出含有本地字體的PDF:

這裏需要注意,使用本地字體風險也是不可避免的,如果用戶沒有安裝對應字體,在網頁中瀏覽器會使用其他字體進行渲染,倒是PDF依舊會有出現亂碼的風險。解決方法是需要從服務器中下載目標字體或使用其他字體作爲替代。

拓展閱讀

React + Springboot + Quartz,從0實現Excel報表自動化

電子表格也能做購物車?簡單三步就能實現

使用純前端類Excel表格控件SpreadJS構建企業現金流量表

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章