這陣子花了一些時間研究 Unicode 萬國碼,看著看著就研究起 Emoji 表情圖示來了。過程中還跑去看了 Unicode® Emoji 官方規格,要是沒有先建立對 Unicode 的理解,要完全看懂 Emoji 的來龍去脈是不太容易的。研究的過程中,還發現了一些有趣的冷知識,欲知詳情請繼續看下去! 😉
首先,先來講怎樣在文件中使用 Emoji 表情圖示。這過程說簡單很簡單,要說複雜其實也有點複雜。基本上,你有 4 種方式可以在文件中輸出 Emoji 表情圖示:
- 直接輸入 Emoji 字元
- 將 12 個按鍵符號轉換為 Emoji 圖示
- 在現有的 Emoji 字元後方加入菲茨派屈克修飾符 (膚色深度)
- 透過 零寬連字(ZWJ) 將多個 Emoji 連接在一起
直接輸出 Emoji 字元
其實每一個 Emoji 就是一個 Unicode 字元,就跟一般文字一樣,所以你大可將 Emoji 字元放在任意字串中,完全沒有問題!
任何支援 Unicode (UTF-8, UTF-16, UTF-32) 的文件,都可以完全合法的放入 Emoji 字元,使用者的作業系統 (包含行動裝置) 只要有安裝含有 Emoji 的字型 (大多已內建),就可以正確顯示 Emoji 表情圖示。
-
直接上網搜尋並複製貼上
大部分 Emoji 字元都可以上網找到,直接透過複製/貼上就可以立即使用,相當便利:
-
使用 Windows 10 的 Emoji 輸入法視窗
從 Windows 10 周年更新內建了一個 Win+.
快速鍵,可以叫出 Emoji 鍵盤來用,非常方便!
-
透過 HTML Entities 語法輸出到 HTML 文件中
&what: Discover Unicode & HTML Character Entities
🔴
-
透過 JavaScript 的 Unicode escape sequences 寫在字串中
在寫 JavaScript 字串的時候,直接將 Emoji 字元寫入字串是可以的,例如:
var a = '💁👌🎍😍';
JavaScript 有個 Unicode escape sequences 表示法,可以用在字串中,假設 Unicode 的字碼為 U+1F197
( 🆗 ),那麼 JavaScript 有兩種表示法:
-
ES6 (ES2015) 可以使用 Unicode 的 Code point (碼點) 來表示一個 Unicode 文字 🍔
var emoji1 = '\u{01F354}';
var emoji2 = String.fromCodePoint(0x1F354);
※ 請注意:即便 ES6 可以用 Unicode 的 Code point (碼點) 來表示一個 Unicode 文字,但事實上內部的文字編碼主要還是以 UTF-16 為主。
-
ES5 僅支援 \uhhhh
表示法,大部分 Emoji 字元被定義在 BMP 以外的字碼區域,你必須把一個 Unicode 字碼 (Code point) 轉換成兩個 UTF-16 碼元 (code unit) 才行,透過 surrogate pair 的方式來表達一個 Unicode 字元。所以 U+1F197
只能用以下語法來寫: 🆗
'\uD83C\uDD97'
你可以透過 ES6 (ES2015) 提供的 API 來計算出 ES5 可以使用的兩個 UTF-16 碼元 (code unit):
var hb = '\u{01F197}'[0].codePointAt(0).toString(16); // \ud83c
var lb = '\u{01F197}'[1].codePointAt(0).toString(16); // \udd97
也可以透過以下函式將 UTF-32 字碼轉換為兩個 UTF-16 的表示法:
function toUTF16(codePoint) {
var TEN_BITS = parseInt('1111111111', 2);
function u(codeUnit) {
return '\\u'+codeUnit.toString(16).toUpperCase();
}
if (codePoint <= 0xFFFF) {
return u(codePoint);
}
codePoint -= 0x10000;
// Shift right to get to most significant 10 bits
var leadingSurrogate = 0xD800 | (codePoint >> 10);
// Mask to get least significant 10 bits
var trailingSurrogate = 0xDC00 | (codePoint & TEN_BITS);
return u(leadingSurrogate) + u(trailingSurrogate);
}
使用範例如下:
toUTF16(0x1F197)
將 12 個按鍵符號轉換為 Emoji 圖示
Emoji 定義了 12 個按鍵符號 (0123456789#*
),只要加入一組 2 個字元的 Emoji Keycap Sequence ('\uFE0F\u20E3'
) 就可以把文字自動轉成 Emoji 圖示。
var keycap = '\uFE0F\u20E3';
console.assert('0️⃣' === '0' + keycap);
console.assert('1️⃣' === '1' + keycap);
console.assert('2️⃣' === '2' + keycap);
console.assert('3️⃣' === '3' + keycap);
console.assert('4️⃣' === '4' + keycap);
console.assert('5️⃣' === '5' + keycap);
console.assert('6️⃣' === '6' + keycap);
console.assert('7️⃣' === '7' + keycap);
console.assert('8️⃣' === '8' + keycap);
console.assert('9️⃣' === '9' + keycap);
console.assert('#️⃣' === '#' + keycap);
console.assert('*️⃣' === '*' + keycap);
在現有的 Emoji 字元後方加入菲茨派屈克修飾符 (膚色深度)
在 Emoji 表情圖示的 Unicode 規格中,有個特別的 EMOJI MODIFIER FITZPATRICK (菲茨派屈克修飾符) 可用,這個 修飾符 (Modifier) 也是一個合法的 Unicode 字元,必須緊接著在 Emoji 字元後面出現。
目前全世界人類的 膚色分級 (Fitzpatrick scale) 是 1975 年由一位叫做 Thomas B. Fitzpatrick 的人訂定出來的,他當初定義了 6 種膚色等級。(Type 1 ~ Type 6)。研究 Emoji 竟然還能學習到這種冷知識,哈!
在 Emoji 表情符號中,總共定義了 5 個字元,用來代表 Emoji 的顏色深度。為什麼不是 6 個呢?因為 Type 1 與 Type 2 顏色太相近了,在電腦螢幕上不容易區分,索性就合併了。這五個字元分別是:
字元名稱 |
Code point |
字元 |
UTF-16 (使用 JavaScript 字串) |
UTF-8 |
FITZ-1-2 |
U+1F3FB |
🏻 |
0xD83C 0xDFFB ('\uD83C\uDFFB' ) |
0xF0 0x9F 0x8F 0xBB |
FITZ-3 |
U+1F3FC |
🏼 |
0xD83C 0xDFFC ('\uD83C\uDFFC' ) |
0xF0 0x9F 0x8F 0xBC |
FITZ-4 |
U+1F3FD |
🏽 |
0xD83C 0xDFFD ('\uD83C\uDFFD' ) |
0xF0 0x9F 0x8F 0xBD |
FITZ-5 |
U+1F3FE |
🏾 |
0xD83C 0xDFFE ('\uD83C\uDFFE' ) |
0xF0 0x9F 0x8F 0xBE |
FITZ-6 |
U+1F3FF |
|
0xD83C 0xDFFF ('\uD83C\uDFFF' ) |
0xF0 0x9F 0x8F 0xBF |
以下是不同的 Emoji 在加上菲茨派屈克修飾符之後的比較表:
Code point |
Default |
FITZ-1-2 |
FITZ-3 |
FITZ-4 |
FITZ-5 |
FITZ-6 |
U+1F9D2: 小孩 |
🧒 |
🧒🏻 |
🧒🏼 |
🧒🏽 |
🧒🏾 |
🧒🏿 |
U+1F466: 男孩 |
👦 |
👦🏻 |
👦🏼 |
👦🏽 |
👦🏾 |
👦🏿 |
U+1F467: 女孩 |
👧 |
👧🏻 |
👧🏼 |
👧🏽 |
👧🏾 |
👧🏿 |
U+1F9D1: 大人 |
🧑 |
🧑🏻 |
🧑🏼 |
🧑🏽 |
🧑🏾 |
🧑🏿 |
U+1F468: 男人 |
👨 |
👨🏻 |
👨🏼 |
👨🏽 |
👨🏾 |
👨🏿 |
U+1F469: 女人 |
👩 |
👩🏻 |
👩🏼 |
👩🏽 |
👩🏾 |
👩🏿 |
我簡單透過 JavaScript 示範將 🧑 (大人) 膚色改成 🧑🏿 (黑人) 的程式寫法:
var adult = '🧑';
var fitz6 = '\uD83C\uDFFF';
var black = adult + fitz6; // 只要透過簡單的字串相加就可以完成!
console.log(black);
請注意:不是所有 Emoji 都能加上膚色,只有跟「人類」有關的 Emoji 才能這樣用,例如 Emoji 中有出現臉、手、腳、身體的,都可以這樣用。目前 Unicode v11.0 定義了 106 個 Emoji 圖示是可以加上 EMOJI MODIFIER FITZPATRICK 字元的,完整清單可以參考這裡。
透過 零寬連字(ZWJ) 將多個 Emoji 連接在一起
這個就真的很酷了,我以前一直很納悶有些 Emoji 到底是怎樣產生的,深入研究後才發現,原來 Emoji 這麼好玩,除了有幾千種不同的 Emoji 之外,還可以將其組合成各種千變萬化的玩法。
Unicode 中有個特殊的 零寬連字(ZWJ) 符號 (U+200D
),這基本上是一個合法的 Unicode 文字,只是他預設是看不見的 零寬(Zero Width) 字元。這個字元通常用在排版用途,不過卻被 Emoji 拿來用了。你可以透過這個字元,任意串接兩個不同的 Emoji 字元,然後就可以創造出新的、不存在 Emoji 清單中的全新 Emoji 字元。
這邊我做個非常簡單的示範,我直接把 👨 (男人) 與 👩 (女人) 串加起來,但中間卡一個 ZWJ 字元,這個 Emoji 就會自動變成 👨👩 (一男一女):
var man = '👨';
var women = '👩';
var zwj = '\u200D';
console.log(man + zwj + women);
如果希望顯示一家三口全家福的 Emoji 圖示,可以直接把 👨 (男人) 、 👩 (女人) 與 🧒 (男孩) 串加起來,但不同的字元中間都要卡一個 ZWJ 字元,此時 Emoji 就會自動變成 👨👩👦 (一男一女外加一個男孩):
var man = '👨';
var women = '👩';
var child = '👦';
var zwj = '\u200D';
console.log(man + zwj + women + zwj + child);
相同的邏輯,如果你想顯示一家三口全家福,但小孩是個女兒的話,的 Emoji 圖示,可以直接把 👨 (男人) 、 👩 (女人) 與 👧 (女孩) 串加起來,不同的字元中間依然要卡一個 ZWJ 字元,此時 Emoji 就會自動變成 👨👩👧 (一男一女外加一個女孩):
var man = '👨';
var women = '👩';
var child = '👧';
var zwj = '\u200D';
console.log(man + zwj + women + zwj + child);
如果有兩個小孩呢?沒問題! 👨 + 👩 + 👦 + 👧 = 👨👩👦👧
var all = ['👨', '👩', '👦', '👧'];
var zwj = '\u200D';
console.log(all.join(zwj));
基本上,你要加幾個人都可以!而且在這兩性平權的時代,兩個爸爸、兩個媽媽也不奇怪,想親手試試 Emoji 怎樣設定嗎?
👨👨👦👧
var all = ['👨', '👨', '👦', '👧'];
var zwj = '\u200D';
console.log(all.join(zwj));
👩👩👦👧
var all = ['👩', '👩', '👦', '👧'];
var zwj = '\u200D';
console.log(all.join(zwj));
喔!爸爸是巴西人、媽媽是黑人?沒問題!I got you back! 👨🏻👩🏿👦👧
var fitz1 = '\uD83C\uDFFB';
var fitz6 = '\uD83C\uDFFF';
var all = ['👨'+fitz1, '👩'+fitz6, '👦', '👧'];
var zwj = '\u200D';
console.log(all.join(zwj));
你是一位白人、女性、而且是一位學生?👩🏻🎓
var fitz1 = '\uD83C\uDFFB';
var all = ['👩'+fitz1, '🎓']; // 加上學士帽 Emoji 即可!
var zwj = '\u200D';
console.log(all.join(zwj));
套用 ZWJ 字元的 Emoji 完整清單可以參考這裡。
注意事項
雖然 Unicode 明確定義了許多 Emoji 的字碼,但還是有很多平台會自己定義額外的 Emoji 圖示,因此不是所有的 Emoji 大家都看的到,這點必須特別注意。
有些沒有被定義在 Emoji 的 Unicode 符號,在特定作業系統平台也會特別做成彩色版的 Emoji 圖示,這部分各位就不用過於擔心,就算在其他平台看不到這個圖示,還是會顯示「文字版」的符號樣式,但也就沒有顏色了。
Unicode 標準定義的 Emoji 清單,可以從 Full Emoji List, Unicode v11.0 取得!
相關連結