【Twemoji】かわいい絵文字をOSで共通の画像として表示する【React】の絵文字

【Twemoji】かわいい絵文字をOSで共通の画像として表示する【React】

2022-04-27

2022-04-27

はじめに

ドライフルーツ、砂糖のせいで不健康がちこふです。

実は Twemoji は本ブログサイトにも導入したばかりですが、とても気に入っています。

Zenn を使っている時から良いな〜と感じ、埋め込むことにしました。

こんな感じです。

実際にサイトで使っている様子のスクリーンショット

方針

本サイトの記事は markdown ファイルで管理しており、FrontMatter と呼ばれる場所で「タイトル、説明文、投稿日、更新日、絵文字」などを管理しています。

FrontMatter について:https://middlemanapp.com/jp/basics/frontmatter/


その絵文字の場所には、OS ごとに依存した絵文字を配置しています。

以下の写真のように、同じ絵文字でも「Windows・Mac・Android」などで別々の絵文字が使われます。

絵文字のOSごとの差

実際に以下のサイトで確認できます。

引用元サイト:https://emojipedia.org/grinning-face/

その差をなくして表示したい!という要望に答えるのが Twemoji です。画像で表現するので OS による差がなくなる、という訳です。

余談ですが、「Windows・Mac・Android」などといったのは、主に Web ブラウザからブログなどのサイトにアクセスするから、上記を挙げました。

厳密には、Windows というより Microsoft、Mac というより Apple、Android というより Google です。。。Sumsung は Garaxy などのスマホでの表示ですね。

環境

React を用いて構成していますが、React でなくても動きます。

Vue や素の JavaScript などでも同様です。

terminal

1❯ node -v 2v16.14.0

package.json

package.json
1... 2"dependencies": { 3 ... 4 "gray-matter": "^4.0.3", 5 "react": "^17.0.2", 6 "react-dom": "^17.0.2", 7 "react-markdown": "^8.0.1", 8 "twemoji-parser": "^14.0.0" 9 }, 10 "devDependencies": { 11 ... 12 "@types/node": "17.0.4", 13 "@types/react": "17.0.38", 14 "@types/twemoji-parser": "^13.1.1", 15 "tailwindcss": "^3.0.7", 16 "typescript": "4.5.4" 17 }

ソースコードと解説

具体的なコードを用いて説明しますが、あくまで一部分に組み込むことを目的としています。

そのため、アプリケーション全体のコードは記載しません。

Markdown ファイル

以下のように FrontMatter を与えます。この絵文字は OS に依存する絵文字なので、端末によって表示が変わると思います。

example.md
1--- 2... 3emoji: '😃' 4... 5---

型を定義

1export type MatterType = { 2 ... 3 emoji: string 4 ... 5}

実際に parse して表示する

parseするとき、emojiundefinedになった対処として別の絵文字を渡すようにしています。

parseした結果、EmojiEntityの配列が返ってくるので、最初のものを受け取ります。

というのも、引数には絵文字を含んだ文字列を与えられるからです。例えば、parse('こんにちは😀')としても絵文字だけ返ってくるということ。

1import { EmojiEntity, parse } from 'twemoji-parser' 2const { emoji } = data 3// data: MatterType 4const emoji: EmojiEntity = parse(emoji || '😀')[0] 5/// 6<img 7 loading="lazy" 8 className="" 9 height="100px" 10 width="100px" 11 alt={`${title}の絵文字`} 12 src={emoji.url} 13/> 14...

ちなみにEmojiEntityは以下のように定義されており、urlとしてtwemojiの画像のURLが入っているので、これを img などの src として指定します。

1export interface EmojiEntity { 2 /** 3 * @default 'emoji' 4 */ 5 type: typeof TypeName 6 text: string 7 /** 8 * @default '' 9 */ 10 url: string 11 /** 12 * [startIndex: number, lastIndex: number] 13 */ 14 indices: [number, number] 15}

余談:絵文字は単純ではない

ご存じの方はスキップしてください。絵文字に関して知らないと、実装したり使う上でトラブルが起こる可能性があります。

僕は実際に起こりました、なんでこの絵文字は変換できるのに、別の絵文字は変換できないんだ、という感じ)


絵文字の中には、複数の絵文字の組み合わせでできた絵文字もあります。

つまり、バイト列では長くなります。

文字列長を求めると一文字ではない発生要因です。

それを対処するために必要なのが以下です。

twemoji-paser を使う理由

https://stackoverflow.com/questions/48419167/how-to-convert-one-emoji-character-to-unicode-codepoint-number-in-javascript

これを参考にコードポイントに変換できるのですが、あくまで絵文字が一文字入ってくる前提に使えるものです。

コードの型情報に絵文字型を作るのも変だな、と感じたので、絵文字だけを確実に取り出せるものが欲しかったです。

静的な Markdown ファイルの FrontMatter に emoji:””という形で書いているが、ヒューマンエラーで" "と入力してしまった場合にも対応できますね。

注意点

大量アクセスがある場合は、画像のミラーサイトやキャッシュをきちんと用意するべき、だと思います。

そういった仕組みを整えないと、CDN とは言え、リクエストが増えすぎることとなり、迷惑がかかってしまいますね。

おわりに

サイトに絵文字を可愛らしく埋め込みましょう。

参考


評価、感想をお願いします!

いただいたご意見を参考に記事を改善しますので、お気軽に入力ください!




共有する