0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PixiJS でサロゲートペアの文字の改行による文字化けを解消する

Posted at

前置き

フォームに入力された文字列を pixi.js で描画するものを作っているときに遭遇した事象です。
ちなみに僕自身、 pixi.js は reference 見ながらなんとなく実装できるくらいです。

何が起きた?

const style = {
  fill: "#fff",
  fontSize: 40,
  wordWrap: true,
  breakWords: true,
  wordWrapWidth: 100,
};
const message = new PIXI.Text("🤗🤗🤗🤗🤗", style);
container.addChild(message);
// output: 
// 🤗🤗�
// �🤗🤗

サロゲートペアの部分で分断されて出力されてしまいました。

対処

  1. サロゲートペアの判定をする
  2. TextMetrics を取得する
  3. 文字列の長さを比較する (元の文字列・改行を考慮した文字列)
  4. 長さが合わなかったら wordWrapWidth を調整する
// サロゲートペア判定
function stringToArray(str: string) {
  return str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
}

const text = "🤗🤗🤗🤗🤗";
const style = {
  fill: "#fff",
  fontSize: 40,
  wordWrap: true,
  breakWords: true,
  wordWrapWidth: 100,
};

// TextMetrics 取得
const textMetrics = PIXI.TextMetrics.measureText(text, style);

// 文字列の長さ
const beforeTextLength = stringToArray(text).length;

// 行ごとの文字列の長さを足した数
let afterTextLength = textMetrics.lines.reduce((pv, v) => pv + stringToArray(v).length, 0);

// output: 5 6
console.log(beforeTextLength, afterTextLength);

// 文字サイズ分横幅を増やして試す
let retry = style.fontSize;
let wordWrapWidth = style.wordWrapWidth;
// retry上限回数 または 文字列の長さが同じ になるまで試す
while (retry > 0 && beforeTextLength !== afterTextLength) {
  retry -= 1;
  wordWrapWidth += 1;
  afterTextLength = PIXI.TextMetrics
    .measureText(text, { ...style, wordWrapWidth })
    .lines.reduce((pv, v) => pv + stringToArray(v).length, 0);
}

const message = new PIXI.Text(text, { ...style, wordWrapWidth });
container.addChild(message);
// output: 
// 🤗🤗🤗
// 🤗🤗

最初にこの事象に遭遇したときは、もっと複雑なことしないといけないのかなーと思ったんですが、意外となんとかなりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?