ホームページ  >  記事  >  ウェブフロントエンド  >  フロントエンド テキスト truncation_html/css_WEB-ITnose

フロントエンド テキスト truncation_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-21 08:53:331138ブラウズ

誤解

プロダクトを設計する際、多くのプロダクトマネージャーやエンジニアは「文字の幅は必ずしも同じであるとは限らない」という概念を持っていないため、「n文字以上は切り詰められてしまう」ということがよくあります。と表示され、英語の数字は 1 文字、中国語は 2 文字としてカウントされます。

効果を表示するために、フロントエンドは欧文フォントファミリーを優先するフォントファミリー設定を採用することがよくあります。つまり、欧文文字は欧文フォントを使用します。と中国語の文字は中国語フォントを使用します。文字数に応じてテキストの幅を制御するのが難しくなります。まず、ノンコードコンテンツ自体は必ずしも等幅欧文フォントでの表示に適しているわけではありません。次に、たとえ等幅の欧文フォントを使用したとしても、漢字の幅をちょうど 2 倍にすることは基本的に不可能です。この需要を満たすには、欧文フォントを放棄し、欧文文字には中国語フォントを使用し、Zhongyi シリーズのいくつかのフォント (Windows では「Songti」である SimSun など) を使用するしかありません。 (醜いことは言うまでもありませんが、Windows でのニーズしか満たせません。)

この種の要求は、特定の文字エンコーディングの長さの概念と混同されることがよくあり、「長さ制限 n バイト」が生じます。英語の数字は 1 バイト、漢字は 2 バイトとして数えます。」これは奇妙なことわざです。

ところで、この「欧文文字は同じ幅を占め、漢字はその 2 倍の幅を占める」という要件は、通常はプログラマーのコード エディターにのみ存在します。この種の強迫性障害の末期段階にあり、Zhongyi Songti を使用したくない場合は、Belleve が製造する Inziu を試してみることを検討してください。

アイデアと原則

フロントエンドの場合、データベース ストレージの制限は心配する必要はありません。前述の「疑似要件」を見ると、実際の要件は多くの場合、「特定の高さを超えて切り詰められた表示」または「特定の行数を超えて段階的に表示」など、視覚的な観点からのものです。実装方法の違いにより、実際には「単一行の切り捨て」、「複数行の切り捨て」、「高さによる切り捨て」に分けることができます。費用と効果の観点からは、「導入難易度」「効果の精度」「コンテンツの制限はあるか」「ページ変更に対応できるか」など、検討すべき点は細かくあります。この記事では、さまざまな実装コードをリストするつもりはなく、いくつかの関連する問題とアイデアについてのみ説明します。

既存の実装ソリューションを確認するには、次の記事を参照してください:

  • ELLIPSE MY TEXT…
  • Line Clampin' (複数行テキストの切り詰め)
  • CSS 省略記号: Pure CSS で複数行の省略記号を管理する方法

text-overflow: ellipsis

Firefox 7 以降、これについてはあまり言うことはないと思います。この CSS プロパティのサポートにより、これは 99% の場合において単一行テキストの切り捨てに最適な選択肢となっています。実装の難易度はほぼゼロで、切り捨て効果は正確で、コンテンツには画像、リンク、その他のコンテンツも含めることができ、幅が変更された場合に自動的に応答できます。互換性も非常に優れています (もちろん、いくつかの問題が発生する可能性があります)。 IE の下位バージョンでの追加コンテンツ) 要素の 1 つのレイヤーをネストする特殊なケース)。 Firefox 7 より前のバージョンをサポートするにはどうすればよいですか?可能な限りあなたのニーズを捉えるようにしてください。他の選択肢を考えることはもはや不可能です。

しかし、他の要件が付加されている場合、純粋な CSS ソリューションでは要件を満たすことができない可能性があります。たとえば、マウスを移動した後、テキストが切り取られた場合にのみ、フローティング レイヤーを介してすべてのテキストを表示したい場合があります。また、行末に切り取ることはできないが変数を含むコンテンツがある場合もあります。幅。

コンテンツの幅を計算する

Baidu の以前の Tangram ライブラリには、バージョン 1.x に textOverflow メソッドがあり、指定された幅に従ってテキストの 1 行を切り詰めます。大まかなアプローチは、各文字の幅を計算し、プラス... が指定された幅よりわずかに小さい境界を見つけて、後続の文字を切り捨てることです。パフォーマンスを向上させるために、ASCII 文字の幅 (不等幅) と中国語の文字の幅 (等幅漢字) が事前に計算されてキャッシュされ、その他の文字はリアルタイムで計算されます。幅を計算するとき、指定された要素内に div 要素が追加され、元の要素のテキスト レイアウト関連の CSS プロパティをすべて継承します。しかし実際には、コンテンツに元々さまざまなスタイルのテキストが混在している場合、計算は正確ではない可能性があります (たとえば、div:first-child と ::first-letter にスタイルがあります)。このソリューションは当時すべてのブラウザと互換性がありましたが、処理されるコンテンツは基本的にプレーン テキストのみであり、その完全性にはいくつかの欠陥もありました。

同様に、scrollWidth を使用して、コンテンツが水平方向にオーバーフローするかどうかを判断することもできます。オーバーフローした場合、残りのコンテンツが省略記号で完全に表示されるまで、末尾のコンテンツを切り続けることができます。実装は以前のソリューションよりもシンプルかつ正確である必要がありますが、前者のソリューションは、幅を事前に計算した後にコンテンツをインターセプトするときに、UI 上の正確な幅をリアルタイムで読み取る必要がないため、パフォーマンスはこれよりも高くなります。

コンテンツの行数を計算する

WebKit ブラウザーで表示される行数を制限するには、-webkit-line-clamp CSS プロパティの非標準実装を使用できます。もよく知られています。モバイル側ではさらに多くのアプリケーション シナリオが存在する可能性があり、デスクトップ側で WebKit ブラウザのみをサポートすることは困難です。 CSS で問題を直接解決できない場合、JavaScript でどのように解決できるでしょうか?

考えやすいのは、高さを行の高さで割ることです。行の高さが指定されていない場合は、getComputedStyle を通じて実際の行の高さを取得する必要があります。ただし、line-height がデフォルト値の場合、計算される値は正常であり、必ずしも確定した値ではありません。したがって、line-height による計算は、行の高さの値を自分で指定するシナリオに適しています。たとえば、Clamp.js では、すべてのブラウザのデフォルト値が 1.2 であるとして、通常の値が処理されます。言うまでもなく、行の高さを超える画像などのコンテンツが存在する可能性があるため、高さは行の高さと行数の積ではありません。

さらに、私の知る限り、コンテンツの行数を正確に

決定するために使用できる主な方法が 2 つあります。このタイプのメソッドの特徴は、行の高さを固定値にする必要がないことです。たとえば、行の高さを変更するためのアイコンが中央に埋め込まれています。高さが不確かな行数を制限することが妥当かどうかについては議論しません (コンテンツを表示するとき、高さの制限は行数ではなく高さの制限から決まることが多いため)。次の点を見てみましょう。具体的なアプローチ。

Use Element.getClientRects()

テストによると、IE8+ およびその他の最新のブラウザーでは、このメソッドには、表示: inline: によって返される DOMRectList オブジェクトの長さの要素に対する機能があります。 call result は、要素がレンダリングされた後の行数と同じです。このようにして、カウントする必要があるコンテンツを display: インライン コンテナーに置くことができます (たとえば、元々は e388a4556c0f65e1904146cc1a846bee 要素内のテキストでしたが、現在は p > span 構造に変更されています)。 ただし、現在 WebKit では、 の疑いのある バグがあります。この表示: インライン コンテナーに子要素がある場合、getClientRects の結果にはこれらの子要素のアウトラインが含まれます。カウントエラーです。仕様にはこのメソッドの計算ロジックが詳しく記載されていないのに、なぜバグの疑い

と言われているのでしょうか?いくつかの特定のスタイルがコンテナに追加されると、計算結果は予想される結果と一致するためです。詳細については、この問題とデモを参照してください。

Selection.modify() を使用します

これは非標準の DOM インターフェイスですが、WebKit と Gecko の両方が実装しています (IE/Edge ではサポートされていません)。

一般原則は次のとおりです。選択範囲を要素の先頭に配置し、

selection.modify('extend', 'forward', 'lineboundary');

を実行すると、選択範囲は次のようになります。行末に展開し、selection.focusNode がまだコンテナ内にある場合は、

selection.modify('extend', 'forward', 'character');

を使用して 1 文字後方に拡張します。この時点で、selection.focusOffset が変更され、次の行にコンテンツがあることが示されます。繰り返し、指定した要素の「行数」を取得できます。

ブラウザの互換性の点で、この方法には CSS 方法よりも Firefox のみがサポートされていることは明らかです。ただし、前の方法に比べて優れている点は、改行文字の位置がすぐにわかるため、インターセプト時に最終内容をインターセプトして行数分リトライを繰り返す必要がないことです。

コンテンツの高さを計算する

コンテナの高さを指定した後、scrollHeight と clientHeight を比較することで、要素コンテンツの高さがコンテナの範囲を超えているかどうかを簡単にテストできます。指定された高さを超えると、末尾の内容はオーバーフローしなくなるまで繰り返し切り詰められます。

コンテンツをインターセプト

コンテンツがプレーンテキストの場合、非常に簡単です。順番に最後の文字を削除し、コンテンツが幅/行数/高さを超えているかどうかを確認するだけです。限界。テキストが長い場合は、二分法を使用して実行効率を最適化できます。同時に、コンテンツがキャッシュされている場合、コンテンツ領域の幅が大きくなった場合、状況に応じて以前に傍受されたテキストを再充填することができ、CSS と同様の適応効果が得られます。

しかし、コンテンツ内に他の HTML 要素がある場合、物事はそれほど簡単ではありません。実行可能な方法は、コンテンツが残っている最後の葉ノードを常に検索し、それがテキスト ノードの場合は最後の文字を削除し、それ以外の場合はノードを直接削除します。幅が増加すると、以前のコンテンツを復元するのはそれほど簡単ではありません。まず、以前に削除されたすべての要素の参照を保持する必要があります (イベント リスナーが存在する可能性があるため)。その後、テキストと要素ノードを再充填できます。も以前と同様に削除する必要があります。DOM 構造は復元されます。その場合、以前に削除したときの操作のすべてのステップを記録し、回復時にはその逆の手順を実行する必要があるかもしれません。理論的には可能ですが、実装はより複雑になる可能性があります。

概要

ご覧のとおり、CSS ベースのソリューションは非常に正確で、ページ レイアウトが変更され、ブラウザーのビューポート サイズが変更された場合の応答性が高くなりますが、特定のシナリオにのみ対応できます。 JS を使用したソリューションは柔軟性の点で優れている場合がありますが、より多くの作業が必要になります。また、処理するコンテンツが多い場合、JS メソッドを使用するとパフォーマンスのボトルネックが発生する可能性があります。結局のところ、一般に、UI の実際の表示スタイルを読み取るためのインターフェイス呼び出しコストが比較的高くなります。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。