對於渲染引擎而言,不論我們如何用 override-colors
的方式調整 Color Font 的顏色,顯示的都是「字」,在記憶體裡面儲存的其實是該字符的「碼位」與「字型資訊」。
如果我們把這個「字」複製到別的地方,在沒有設定 css 的情況下,顏色設定就會跑掉,通常會以預設的第 0
個基本色盤表示。
所以如果想要保存我們設定的「彩色字」、或是讓使用者可以自由地分享,除了連 css 資訊一併紀錄之外,另一種方式就是將文字轉成圖片。
在 HTML 標準裡面,我們可以透過 canvas
標籤來繪製圖案,以繪製一個矩形來說,先在 html 裡面定義一個 300x300 的 畫布(canvas),為了更清楚範圍,在這裡替畫布補上一個黑色外框,實際上是可以省略的:
<canvas id="myCanvas" width="300" height="300"
style="border:1px solid black">
</canvas>
接著透過 javascript,指定該畫布後,藉由 canvas.getContext
繪製想要的東西,在這裡我們指定 2d
,也就是二維的圖像(除此之外也可以繪製 3D 的 webgl
等,但瀏覽器的支援程度不一,很容易破圖)。接著,我們填入一個自座標 (x, y) = (30, 50)
起算,長寬各為 80
、100
的 #FF0000
紅色矩形:
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(30, 50, 80, 100); // (x, y, w, h),以左上角為原點
<canvas>
標籤除了製作幾何圖形之外,也可以用來繪製文字。假設我們把「字」被記錄在 id 為 #dolphin
這個 <div>
tag 裡面:
<div id="dolphin" style="font-family: Noto Color Emoji; font-size: 10em">🐬</div>
我們想要繪製出一模一樣大小的圖片,首先就必須要讓畫布 #myCanvas
的大小和 #dolphin
這個 DOM 的大小一致。因此,和上面畫圖不同的是,這次我們不在 #myCanvas
的 tag 裡預設長寬尺寸,而是應該要透過參照的方式讓 #myCanvas
獲取 #dolphin
的長寬尺寸:
canvas.width = document.getElementById("dolphin").clientWidth;
canvas.height = document.getElementById("dolphin").clientHeight;
接著,我們要讓畫布恢復成空白的狀態。之所以要這樣做,是因為我們也許會重複使用這個畫布,如果上一次的結果沒有先清掉的話,就會將這一次的結果直接疊在舊稿之上,透過每次繪製前的重設畫布,也算是一種防呆機制吧!此外,背景設定為白色的之後,只要另存成 *.png
格式,就會是去背的樣式。
ctx.clearRect(0, 0, canvas.width, canvas.height);
接著就是設定需要的字型資訊以及字型大小,就可以將字轉成圖片啦:
ctx.font = "10em Noto Color Emoji";
ctx.fillText("🐬", canvas.width / 2, canvas.height / 2);
不過,如果把圖片打開來看的話,會發現畫質其實不是那麼好,這是因為我們預設都是使用 1:1 的方式去渲染 #dolphin
這個 tag 的 🐬,雖然對於向量儲存的 COLR/CPAL Color Font 來說,放大縮小都不會讓字型失真,但因為我們已經將他轉成點陣形式的圖片了,所以會遇到畫質不佳的問題。
至於解決方式呢?也很簡單,就是在更大張的畫布上繪製就好——我們可以定義一個 scaleProp
參數來控制畫布大小的倍率。
// 縮放的參數,假設放大十倍
const scaleProp = 10
canvas.width = document.getElementById("dolphin").clientWidth * scaleProp;
canvas.height = document.getElementById("dolphin").clientHeight * scaleProp;
// 讓繪製的結果也跟著放大
ctx.scale(scaleProp, scaleProp);
如此一來,我們就能得到更高畫質的「文字圖片」了。
在「文字」的情況下,要轉載或是分享都會麻煩,但要將 <canvas>
的「圖片」轉成圖片就很簡單了,至於是要存成 image/png
、還是 image/jpeg
格式,就端看需求了。
const dataURL = canvas.toDataURL("image/png");
這個 dataURL
已經可以在瀏覽器內開啟了,不過如果想要做一個按鈕,在按下去的時候觸發下載的話,就必需要透過 Dummy Element 來處理:
const downloadLink = document.createElement("a");
downloadLink.href = dataURL;
downloadLink.download = "filename.png";
downloadLink.click(); // 模擬點擊
在今天,我們搞定了文字和圖片的轉換關係,無論使用者怎麼調用 COLR/CPAL Color Font 色盤的顏色,都可以透過轉存圖片的方式保存。