成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

前端玩轉 Emoji 表情符號,看這一篇就夠了!

開發 前端
Emoji 是一種圖形符號,最初由日本電信運營商在 1990 年代引入,用于增強短信和網頁的表達能力。隨著時間的發展,Emoji 已經成為通信中不可或缺的一部分,廣泛應用于社交媒體、電子郵件、即時通訊工具等各種平臺。

Emoji 已經成為我們日常溝通中不可或缺的一部分,本文就來了解一下在前端中如何玩轉 Emoji!

Emoji 基本概念

前置知識

在學習 Emoji 之前,我們先來一些和 Emoji 相關的前置知識。

  • Unicode:

a.定義: 一個國際標準,旨在為世界上幾乎所有的字符(包括字母、數字、符號、標點符號和表情符號等)提供唯一的數字表示形式。它的主要目標是確保在不同的平臺、操作系統和設備之間能夠一致地表示和處理文本數據。

b.特點:

統一編碼:Unicode 為每種語言中的每個字符分配了一個唯一的編號(稱為碼點),從而解決了不同編碼系統之間的不兼容問題。

廣泛覆蓋:Unicode 包含了幾乎所有現代語言的字符,并且還在不斷擴展以支持更多的符號和歷史文字。

多種實現方式:Unicode 支持多種編碼格式,如 UTF-8、UTF-16 和 UTF-32,以便在不同的應用場景中靈活使用。

  • 碼點:
  • 定義: 指在 Unicode 標準中為每個字符分配的一個唯一的數字值。它通常用十六進制表示,并帶有前綴 U+ 來標識這是一個 Unicode 碼點。
  • 舉例:

a.字母 A 的 Unicode 碼點是 U+0041。

b.笑臉 Emoji ?? 的 Unicode 碼點是 U+1F60A。

  • 范圍: Unicode 定義了從 U+0000 到 U+10FFFF 的碼點范圍,總共可以表示超過一百萬個字符。這個范圍分為以下幾部分:
  • 基本多文種平面:從 U+0000 到 U+FFFF,包含最常見的字符。

  • 輔助平面:從 U+10000 到 U+10FFFF,用于表示較少見的字符和 Emoji。

  • 編碼方式: Unicode 有多種編碼方式,常見的有 UTF - 8、UTF - 16 和 UTF - 32。

  • UTF - 8:一種可變長度的編碼方式,使用 1 到 4 個字節來表示一個字符。它對 ASCII 字符采用單字節編碼,兼容 ASCII 標準,因此在互聯網上得到了廣泛應用。

  • UTF - 16:使用 2 個或 4 個字節來表示一個字符,常用于操作系統和編程語言中,如 Java 和 JavaScript 默認使用 UTF - 16 編碼。

  • UTF - 32:固定使用 4 個字節來表示一個字符,編碼簡單直接,但會占用較多的存儲空間。

Emoji 是什么?

Emoji 是一種圖形符號,最初由日本電信運營商在 1990 年代引入,用于增強短信和網頁的表達能力。隨著時間的發展,Emoji 已經成為通信中不可或缺的一部分,廣泛應用于社交媒體、電子郵件、即時通訊工具等各種平臺。

Emoji 本質上是 Unicode 字符集中的一部分,每個 Emoji 都有一個對應的唯一 Unicode 編碼。在最新的 Unicode 16.0 版本中,共指定了 3790 個 Emoji 及其編碼。

圖片圖片

Emoji 對應的 Unicode 編碼:https://unicode.org/emoji/charts/full-emoji-list.html

在支持 Unicode 的環境中,如現代的文本編輯器、瀏覽器等,你可以直接輸入 Emoji 字符來使用它們。許多操作系統都提供了便捷的 Emoji 輸入方法,例如在 Windows 系統中,按下 win + . 組合鍵可以打開 Emoji 選擇器;在 macOS 系統中,按下 Fn + E 組合鍵可以打開 Emoji 輸入菜單。

圖片圖片

不知道你有沒有發現,在不同系統/應用上,Emoji 長的都不太一樣,這是為什么呢?其實,Unicode 為每個 Emoji 分配了唯一的碼點,確保其在不同系統中代表相同的含義,但并沒有規定每個 Emoji 的樣式。因此,每個系統/應用都可以根據各自的設計風格對 Emoji 進行設計,所以就出現了多種風格的 Emoji。

圖片圖片

為了提高一致性,一些項目提供了標準化的 Emoji 集合,可以通過這些項目來自定義 Emoji 顯示,如 Twemoji:https://github.com/googlefonts/noto-emoji

需要格外注意的是:不同的文化對 Emoji 的理解和使用可能有所不同。例如,某些 Emoji 在特定文化中可能有特殊的含義或象征意義。因此,在國際化應用中,需要特別注意 Emoji 的使用,以避免誤解或冒犯。

Emoji 在前端的應用

表示

HTML

  • 直接插入 Emoji:可以在 HTML 文件中的任何文本位置直接插入 Emoji。
<p>今天天氣真好 ??</p>
  • 使用 Unicode 編碼:如果無法直接輸入 Emoji 或者希望使用其 Unicode 編碼,可以使用 Unicode 轉義序列。
<p>今天天氣真好 ?</p>

注意:&#x 后面跟隨的是 Emoji 的 Unicode 碼點的十六進制表示。例如,笑臉 ?? 的 Unicode 碼點是 U+1F60A,在 HTML 中表示為 &#x1F60A;。

CSS

  • 使用 content 屬性: 可以通過 CSS 的 ::before 或 ::after 偽元素以及 content 屬性來插入 Emoji。
.emoji-before::before {
  content: "??"; /* 直接插入 Emoji */
}

.emoji-after::after {
  content: "\1F60A"; /* 使用 Unicode 轉義序列 */
}

注意: 在 CSS 中使用 Unicode 轉義序列時,不需要 &#x 前綴,直接使用 \ 加上十六進制編碼即可。

由于 Emoji 是彩色字符,通常不需要額外的顏色設置。不過,可以通過調整字體大小來控制 Emoji 的顯示大小。

h1 {
    font-size: 2em; /* 將字體大小放大兩倍 */
}

JavaScript

在 JavaScript 中,可以通過以下方式來表示 Emoji:

  • 直接插入 Emoji: 在現代 JavaScript 環境中,可直接在字符串里使用 Emoji 字符。因為現代編輯器和瀏覽器廣泛支持 Unicode 字符,能正確識別和顯示 Emoji。
console.log('Hello ??'); // 輸出: Hello ??
  • 使用 Unicode 編碼: 每個 Emoji 都有對應的 Unicode 編碼,可通過 Unicode 編碼來表示 Emoji。基本多文種平面(BMP)內的 Emoji 用 \u 加 4 位十六進制編碼表示;超出 BMP 的 Emoji 需用代理對或 \u{} 語法表示。
// BMP 內的 Emoji
const heart = '\u2764'; 
console.log(heart);   // ?

// 超出 BMP 的 Emoji,使用代理對
const rocket = '\uD83D\uDE80'; 
console.log(rocket);  // ??

// 超出 BMP 的 Emoji,使用 \u{} 語法
const pizza = '\u{1F355}'; 
console.log(pizza);   // ??

獲取和設置碼點

  • 獲取碼點: 可以使用 codePointAt() 方法來獲取字符串中某個位置的 Unicode 碼點。
const smiley = '??';
console.log(smiley.codePointAt(0).toString(16)); // 輸出: 1f60a
  • 設置碼點: 可以使用 String.fromCodePoint() 方法從 Unicode 碼點創建字符串。
console.log(String.fromCodePoint(0x1F60A)); // 輸出: ??

字符串操作

問題

在 JavaScript 中處理 Emoji 時,尤其是涉及字符串操作,存在一些常見的問題。

  • 代理對: 在 JavaScript 里,字符串中的每個字符通常以 16 位(即 2 個字節)來表示,這遵循的是 UTF-16 編碼規則。不過,Emoji 字符比較特殊,部分 Emoji 字符的編碼超出了基本多文種平面(BMP),需要使用代理對來表示,也就是用兩個 16 位編碼單元來表示一個 Emoji 字符。因此,普通的 .length 屬性可能會返回不正確的字符數,因為它會將代理對視為兩個字符。
const emoji = '??';
console.log(emoji.length); // 輸出: 2 (而不是1)
  • 組合字符: 帶有修飾符的 Emoji 可能由多個碼點組成。例如,?????? 是由三個獨立的 Emoji 組合而成的。因此,在使用 .length計算長度時,得到的結果是不準確的。
const familyEmoji = '??????';
console.log(familyEmoji.length); // 輸出: 8 (而不是1)
  • 截斷問題: JavaScript 中的 slice、substring 或 substr 方法會按照 16 位編碼單元來截取字符串,當使用這些方式截斷包含 Emoji 的字符串時,若在截取過程中恰好截斷了一個代理對,就會產生亂碼。因為這些方法是無法正確處理代理對和組合字符的。
const emojiStr = '??????';
// 錯誤的截取,截斷了代理對
const wrongSubStr = emojiStr.slice(0, 1); 
console.log(wrongSubStr); // ?

內置 API:Intl.Segmenter

ES2021 提供了 Intl.Segmenter,可以解決上面的問題,它是 ECMAScript 國際化 API 的一部分,用于根據語言和區域設置對字符串進行分割。它可以將文本分割成有意義的單元,如單詞、句子或圖元簇,從而更好地處理多語言文本。

Intl.Segmenter 提供了以下分割方式:

  • Grapheme Cluster(圖元簇):將字符串分割為用戶感知的字符單位。這對于處理復雜的 Unicode 字符(如 Emoji 和組合字符)非常有用。
  • Word(單詞):將字符串分割為單詞。
  • Sentence(句子):將字符串分割為句子。

Intl.Segmenter 的基本用法如下:

  • 'en':指定語言環境。可以根據需要更改為其他語言環境,如 'zh' 或 'fr'。
  • { granularity: 'grapheme' }:指定分割粒度,可以是 'grapheme'、'word' 或 'sentence'。
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });

在處理包含復雜 Unicode 字符(如 Emoji 和組合字符)的字符串時,確保準確計算字符數量。

const segmenter = new Intl.Segmenter([], { granularity: 'grapheme' });
const text = 'Hello ????♂? ??????!';
const segments = Array.from(segmenter.segment(text));
console.log(segments.length); // 輸出: 10

第三方庫:grapheme-splitter

對于上面這些問題,也可以使用grapheme-splitter庫來解決,它是一個用于處理 Unicode 字符串的 JavaScript 庫,專門用于將字符串分割成“圖元簇”。圖元簇是用戶感知的一個字符單位,即使它可能由多個 Unicode 碼點組成。例如,帶有膚色修飾符或性別修飾符的 Emoji 實際上是由多個碼點組成的,但用戶通常將其視為一個整體。

grapheme-splitter 的使用場景:

  • 統計字符數量:當需要準確統計字符串中用戶實際看到的字符個數時,例如在文本輸入框中限制字符數量,包含組合字符的字符串使用 .length 計算會不準確,使用 grapheme-splitter 可以得到正確結果。
import GraphemeSplitter from "grapheme-splitter";
const splitter = new GraphemeSplitter();

const str = '??????';
const length = splitter.countGraphemes(str);
console.log(length); // 輸出:1
  • 從字符串中提取特定位置的圖元簇:
import GraphemeSplitter from "grapheme-splitter";
const splitter = new GraphemeSplitter();

const text = 'Hello ????♂? ??????!';
const graphemes = splitter.splitGraphemes(text);
console.log(graphemes);  // 輸出:["H", "e", "l", "l", "o", " ", "????♂?", " ", "??????", "!"]

// 獲取第一個圖元簇
console.log(graphemes[0]); // 輸出: H

// 獲取第7個圖元簇(包含復雜的Emoji)
console.log(graphemes[5]); // 輸出: ????♂?

// 獲取最后一個圖元簇
console.log(graphemes[graphemes.length - 1]); // 輸出: !
  • 字符串截取:在截取字符串時,確保不會截斷組合字符,避免出現亂碼或不完整的字符顯示。
import GraphemeSplitter from "grapheme-splitter";
const splitter = new GraphemeSplitter();

const text = 'Hello ????♂? ??????!';
const graphemes = splitter.splitGraphemes(text);


// 截取前5個圖元簇
const firstFive = graphemes.slice(0, 5).join("");
console.log(firstFive); // 輸出: Hello

// 截取第6到第7個圖元簇
const middlePart = graphemes.slice(6, 7).join("");
console.log(middlePart); // 輸出: ????♂?

// 截取最后1個圖元簇
const lastFive = graphemes.slice(-2).join("");
console.log(lastFive); // 輸出: ??????!
  • 字符遍歷:按用戶感知的字符逐個遍歷字符串,對每個字符進行特定操作。
import GraphemeSplitter from "grapheme-splitter";
const splitter = new GraphemeSplitter();

const str = '????????????♂?';
const graphemes = splitter.splitGraphemes(str);
graphemes.forEach((grapheme) => {
    console.log(grapheme);
});

驗證

在處理 Emoji 時,驗證輸入是否包含有效的 Emoji 字符是一個常見的需求。這可以通過多種方式實現,包括正則表達式以及使用專門的庫來幫助識別和驗證 Emoji。

正則表達式

Emoji 是 Unicode 字符,因此可以使用正則表達式來匹配它們。然而,由于 Emoji 的種類繁多,并且新的 Emoji 不斷被添加到 Unicode 標準中,編寫一個全面的正則表達式可能會比較復雜。下面是一個例子:

const emojiRegex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])[\ufe0e\ufe0f]?(?:[\u0300-\u036f\ufe20-\ufe23\u20d0-\u20f0]|\ud83c[\udffb-\udfff])?(?:\u200d(?:[^\ud800-\udfff]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])[\ufe0e\ufe0f]?(?:[\u0300-\u036f\ufe20-\ufe23\u20d0-\u20f0]|\ud83c[\udffb-\udfff])?)*/gu;

const text = "Hello ????♂? ??????! How are you?";

// 提取所有匹配的 Emoji
const matches = text.match(emojiRegex);

if (matches) {
    console.log('Matches:', matches); // 輸出: ["????♂?", "??????"]
} else {
    console.log('No emojis found.');
}

// 驗證是否包含 Emoji
const hasEmoji = emojiRegex.test(text);
console.log('Contains emoji:', hasEmoji); // 輸出: true

注意: 當使用正則表達式處理包含超出 BMP 的 Unicode 字符(如 Emoji)的字符串時,就需要使用 u 修飾符。u 修飾符的主要作用是開啟 Unicode 模式,讓正則表達式能夠正確處理超過 \uFFFF 的 Unicode 字符。在 JavaScript 里,字符串中的字符默認以 UTF-16 編碼存儲,基本多文種平面(BMP)內的字符可以用一個 16 位的編碼單元表示,但超出 BMP 的字符需要用兩個 16 位的編碼單元(代理對)來表示。在沒有 u 修飾符的情況下,正則表達式會將代理對拆分成兩個單獨的編碼單元進行處理;而使用 u 修飾符后,正則表達式能將代理對視為一個整體,從而正確匹配和處理這些字符。

第三方庫:emoji-regex

emoji-regex 是一個專門用于匹配 Emoji 的 JavaScript 庫。它可以準確地識別和匹配各種類型的 Emoji。

import emojiRegex from 'emoji-regex';
const regex = emojiRegex();

const text = "Hello ????♂? ??????! How are you?";
const matches = text.match(regex);

console.log(matches); // 輸出: ["??", "??", "\u200d", "♂", "\ufe0f", "??", "\u200d", "??", "\u200d", "??"]

Emoji 選擇器

Emoji 選擇器可幫助用戶方便地插入 Emoji 字符。它在許多應用(如聊天軟件、社交平臺、文本編輯器等)中廣泛使用。我們可以根據需要自定義 Emoji 選擇器(可以借助 emojibase 庫的數據來實現),也可以使用開源的 Emoji 選擇器,以下是一些比較熱門的 Emoji 選擇器(npm包名稱)。

  • emoji-mart:

圖片圖片

  • emoji-picker-react:

圖片圖片

  • vue3-emoji-picker:

圖片圖片

責任編輯:武曉燕 來源: 前端充電寶
相關推薦

2020-02-18 16:20:03

Redis ANSI C語言日志型

2022-06-20 09:01:23

Git插件項目

2023-02-10 09:04:27

2022-08-01 11:33:09

用戶分析標簽策略

2021-04-08 07:37:39

隊列數據結構算法

2023-09-11 08:13:03

分布式跟蹤工具

2020-08-03 10:00:11

前端登錄服務器

2020-07-03 08:21:57

Java集合框架

2024-09-23 08:00:00

消息隊列MQ分布式系統

2019-05-14 09:31:16

架構整潔軟件編程范式

2023-10-17 08:15:28

API前后端分離

2018-05-22 08:24:50

PythonPyMongoMongoDB

2017-03-11 22:19:09

深度學習

2022-04-07 10:39:21

反射Java安全

2023-11-18 09:30:42

模型AI

2022-05-19 08:28:19

索引數據庫

2019-04-01 10:43:59

Linux問題故障

2020-10-18 07:32:06

SD-WAN網絡傳統廣域網

2023-11-06 07:21:13

內存結構Jvm

2022-07-06 12:07:06

Python函數式編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久一区二区三区四区五区 | 久久久一区二区 | 欧美精品一二三 | 国产精品亚洲综合 | 久久精品国内 | 七七婷婷婷婷精品国产 | 国产综合在线视频 | 成人免费视频在线观看 | 久草视频在线播放 | 国产精品久久久久免费 | 久久精品国产一区老色匹 | 成人精品在线视频 | 久久国产综合 | 激情视频网站 | 精品一区视频 | 欧美视频在线看 | 噜啊噜在线 | 一区视频在线免费观看 | 成人久久视频 | 久久99精品久久久久久国产越南 | 伊人爽| 国产一区二区电影 | 国产一级淫片免费视频 | 国产日韩一区二区三免费高清 | 亚洲人成在线观看 | 日韩av成人 | 亚洲综合天堂 | 国产精品久久久久久一级毛片 | 亚洲精品www久久久久久广东 | 国产精品不卡 | 91精品久久久久久综合五月天 | 国产婷婷| 91影院在线观看 | 成人一区二区三区在线观看 | 久久久毛片| av在线天天| 亚洲高清在线观看 | 欧美aaaaa | 欧美亚洲日本 | 国产一区免费 | 国产精品成人一区二区 |