用 JavaScript 玩轉 Emoji 表情圖示原來這麼簡單

栏目: JavaScript · 发布时间: 6年前

内容简介:這陣子花了一些時間研究 Unicode 萬國碼,看著看著就研究起 Emoji 表情圖示來了。過程中還跑去看了首先,先來講怎樣在文件中使用 Emoji 表情圖示。這過程說簡單很簡單,要說複雜其實也有點複雜。基本上,你有 4 種方式可以在文件中輸出 Emoji 表情圖示:其實每一個 Emoji 就是一個 Unicode 字元,就跟一般文字一樣,所以你大可將 Emoji 字元放在任意字串中,完全沒有問題!
用 JavaScript 玩轉 Emoji 表情圖示原來這麼簡單

這陣子花了一些時間研究 Unicode 萬國碼,看著看著就研究起 Emoji 表情圖示來了。過程中還跑去看了 Unicode® Emoji 官方規格,要是沒有先建立對 Unicode 的理解,要完全看懂 Emoji 的來龍去脈是不太容易的。研究的過程中,還發現了一些有趣的冷知識,欲知詳情請繼續看下去! :wink:

首先,先來講怎樣在文件中使用 Emoji 表情圖示。這過程說簡單很簡單,要說複雜其實也有點複雜。基本上,你有 4 種方式可以在文件中輸出 Emoji 表情圖示:

  1. 直接輸入 Emoji 字元
  2. 將 12 個按鍵符號轉換為 Emoji 圖示
  3. 在現有的 Emoji 字元後方加入菲茨派屈克修飾符 (膚色深度)
  4. 透過 零寬連字(ZWJ) 將多個 Emoji 連接在一起

直接輸出 Emoji 字元

其實每一個 Emoji 就是一個 Unicode 字元,就跟一般文字一樣,所以你大可將 Emoji 字元放在任意字串中,完全沒有問題!

任何支援 Unicode (UTF-8, UTF-16, UTF-32) 的文件,都可以完全合法的放入 Emoji 字元,使用者的作業系統 (包含行動裝置) 只要有安裝含有 Emoji 的字型 (大多已內建),就可以正確顯示 Emoji 表情圖示。

  1. 直接上網搜尋並複製貼上

    大部分 Emoji 字元都可以上網找到,直接透過複製/貼上就可以立即使用,相當便利:

  2. 使用 Windows 10 的 Emoji 輸入法視窗

    從 Windows 10 周年更新內建了一個 Win+. 快速鍵,可以叫出 Emoji 鍵盤來用,非常方便!

    用 JavaScript 玩轉 Emoji 表情圖示原來這麼簡單

  3. 透過 HTML Entities 語法輸出到 HTML 文件中

    &what: Discover Unicode & HTML Character Entities

  4. 透過 JavaScript 的 Unicode escape sequences 寫在字串中

    在寫 JavaScript 字串的時候,直接將 Emoji 字元寫入字串是可以的,例如:

    var a = ':information_desk_person::ok_hand::bamboo::heart_eyes:';

    JavaScript 有個 Unicode escape sequences 表示法,可以用在字串中,假設 Unicode 的字碼為 U+1F197 ( :ok: ),那麼 JavaScript 有兩種表示法:

    1. ES6 (ES2015) 可以使用 UTF-32 編碼

      var st = '\u{01F197}';
    2. ES5 僅支援 UTF-16 編碼,而大部分 Emoji 字元被定義在 UTF-16 以外的字碼區域 (UTF-32),你必須把一個 UTF-32 字碼 (Code point) 轉換成兩個 UTF-16 字碼才行,透過 surrogate pair 的方式來表達一個 UTF-32 字元,所以 U+1F197 只能用以下語法來寫:

      '\uD83C\uDD97'

      你可以透過 ES6 (ES2015) 提供的 API 來計算出 ES5 可以使用的兩個 UTF-16 字碼:

      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(':zero:' === '0' + keycap);
console.assert(':one:' === '1' + keycap);
console.assert(':two:' === '2' + keycap);
console.assert(':three:' === '3' + keycap);
console.assert(':four:' === '4' + keycap);
console.assert(':five:' === '5' + keycap);
console.assert(':six:' === '6' + keycap);
console.assert(':seven:' === '7' + keycap);
console.assert(':eight:' === '8' + keycap);
console.assert(':nine:' === '9' + keycap);
console.assert(':hash:' === '#' + 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: 男孩 :boy: :boy|type_1_2: :boy|type_3: :boy|type_4: :boy|type_5: :boy|type_6:
U+1F467: 女孩 :girl: :girl|type_1_2: :girl|type_3: :girl|type_4: :girl|type_5: :girl|type_6:
U+1F9D1: 大人
U+1F468: 男人 :man: :man|type_1_2: :man|type_3: :man|type_4: :man|type_5: :man|type_6:
U+1F469: 女人 :woman: :woman|type_1_2: :woman|type_3: :woman|type_4: :woman|type_5: :woman|type_6:

我簡單透過 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 字元。

這邊我做個非常簡單的示範,我直接把 :man: (男人) 與 :woman: (女人) 串加起來,但中間卡一個 ZWJ 字元,這個 Emoji 就會自動變成 :man:‍:woman: (一男一女):

var man = ':man:';
var women = ':woman:';

var zwj = '\u200D';

console.log(man + zwj + women);

如果希望顯示一家三口全家福的 Emoji 圖示,可以直接把 :man: (男人) 、 :woman: (女人) 與 (男孩) 串加起來,但不同的字元中間都要卡一個 ZWJ 字元,此時 Emoji 就會自動變成 :man:‍:woman:‍:boy: (一男一女外加一個男孩):

var man = ':man:';
var women = ':woman:';
var child = ':boy:';

var zwj = '\u200D';

console.log(man + zwj + women + zwj + child);

相同的邏輯,如果你想顯示一家三口全家福,但小孩是個女兒的話,的 Emoji 圖示,可以直接把 :man: (男人) 、 :woman: (女人) 與 :girl: (女孩) 串加起來,不同的字元中間依然要卡一個 ZWJ 字元,此時 Emoji 就會自動變成 :man:‍:woman:‍:girl: (一男一女外加一個女孩):

var man = ':man:';
var women = ':woman:';
var child = ':girl:';

var zwj = '\u200D';

console.log(man + zwj + women + zwj + child);

如果有兩個小孩呢?沒問題! :man: + :woman: + :boy: + :girl: = :man:‍:woman:‍:boy:‍:girl:

var all = [':man:', ':woman:', ':boy:', ':girl:'];
var zwj = '\u200D';
console.log(all.join(zwj));

基本上,你要加幾個人都可以!而且在這兩性平權的時代,兩個爸爸、兩個媽媽也不奇怪,想親手試試 Emoji 怎樣設定嗎?

:man:‍:man:‍:boy:‍:girl:

var all = [':man:', ':man:', ':boy:', ':girl:'];
var zwj = '\u200D';
console.log(all.join(zwj));

:woman:‍:woman:‍:boy:‍:girl:

var all = [':woman:', ':woman:', ':boy:', ':girl:'];
var zwj = '\u200D';
console.log(all.join(zwj));

喔!爸爸是巴西人、媽媽是黑人?沒問題!I got you back! :man|type_1_2:‍:woman|type_6:‍:boy:‍:girl:

var fitz1 = '\uD83C\uDFFB';
var fitz6 = '\uD83C\uDFFF';

var all = [':man:'+fitz1, ':woman:'+fitz6, ':boy:', ':girl:'];
var zwj = '\u200D';
console.log(all.join(zwj));

你是一個白人、女性、而且是一位學生?:woman|type_1_2:‍:mortar_board:

var fitz1 = '\uD83C\uDFFB';

var all = [':woman:'+fitz1, ':mortar_board:']; // 加上學士帽 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 取得!

相關連結


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms on Strings, Trees and Sequences

Algorithms on Strings, Trees and Sequences

Dan Gusfield / Cambridge University Press / 1997-5-28 / USD 99.99

String algorithms are a traditional area of study in computer science. In recent years their importance has grown dramatically with the huge increase of electronically stored text and of molecular seq......一起来看看 《Algorithms on Strings, Trees and Sequences》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具