N 文字目以降を省略するというライブラリはたくさんあるのですが、行数指定できるものは見かけないので作りました。N 行以上になった時は省略したいというケースは結構ある気がするんですが、なぜそういうライブラリは無いのだろう……。
Truncator – NPM
Truncator – Github
使い方
truncate(el, text, { line: 3, ellipsis: '……' });
のような感じで使います。この例だと、要素 el
に文字列 text
を入れて、それが 3 行に収まるように省略します。また、省略記号は ......
を指定してます。
アルゴリズム
以下のような感じのアルゴリズムで動いてます。
1. el
の一行の高さ L を取得する。
2. 行数 n * L で目標の高さ H を算出する。
3. el
に text
を入れてその高さ h を算出する。
4. h <= H を満たす、最大の省略位置を二分探索し、省略後の文字列を el
に入れる。
一行の高さを取得する
一行の高さは window.getComputedStyle(el).lineHeight
で簡単に取得できる……と思いきや、normal
とかが返ってくるケースがあるので、工夫する必要があります。 Truncator では、対象の要素に適当な一文字を入れた時の高さを一行の高さとして扱っています。
省略すべき位置を二分探索する
単純に、center = (left + right) / 2 して、text.substring(0, center)
し、h <= H だったら left を center に、そうでなければ right を center にする二分探索です。ただ、h <= H だったときでも center が解ではないとは限らないため、次の探索でも center を探索空間に含めたままにする必要があります。
最後に
バグ報告大歓迎です!