SVGテキストチュートリアル:Web上のテキスト注釈

公開: 2022-03-11

HTML5とCSS3を使用して、Webブラウザーは、3Dグラフィックス、ソケット、スレッドなど、多くの驚くべきテクノロジーを獲得しました。 これらを使用すると、Webアプリケーションは、それらが使用されているコンピューターおよびオペレーティングシステムの最も洗練された機能のいくつかを利用できます。 Webブラウザーは、アプリケーション開発のための堅牢で用途の広いエコシステムを提供します。これは、私たちがなくてはならない多数の強力なWebアプリケーションの最近の台頭から明らかです。 ただし、まだ欠けているのは、HTMLテキストの注釈と装飾の美しさです。 テキスト装飾とは何ですか? 波状のアンダースコア、凹凸のあるハイライト、波状の取り消し線は、Webブラウザがネイティブサポートを提供していないものの一部です。 これは便利というよりも手の込んだように聞こえるかもしれませんが、JavaScript開発者がこれらのスタイルを作成する機能は、eラーニングリソースやWebベースの電子書籍リーダーなどの側面で役立つ場合があります。 さらに、これは、自然な設計原則を中心に展開するWebアプリケーションのユーザーエクスペリエンスの向上に貢献できます。 少なくとも、そのようなツールを構築することは楽しく、Webブラウザの多くの癖への洞察を提供します。

SVGテキストチュートリアル-テキスト注釈

開発者は、Webブラウザの制限に対する多くの回避策を見つけました。 これらの回避策の多くは、「:: after」疑似要素で画像を使用するため、直感的ではない方法でCSSを使用する必要があります。 これは機能しますが、スタイルと色のペアごとに多くの画像を維持するのは難しいことがよくあります。 この記事では、この問題をエレガントに解決しようとするJavaScriptライブラリの構造を見ていきます。

ライブラリはオープンソースであり、GitHub:TextAnnotatorで入手できます。

概要

このライブラリを開発する際、最も人気のあるWebブラウザ(IE 9以降を含む)との互換性を確保するために特別な注意が払われました。 ただし、この問題を最も解決する方法とは異なり、ライブラリは特にあいまいなCSSトリックに依存していません。 さらに悪いことに、特別なUnicode記号。 代わりに、SVGを使用して、はるかに優れた、よりクリーンなテキスト装飾を実現します。

基本的に、ライブラリは、DIV要素を自動的に作成し、注釈を付けるテキストの下に配置し、背景をSVG画像で塗りつぶすために使用できるアノテーター「クラス」を実装します。 複数のDIVを組み合わせて、装飾をさらにカスタマイズできます。 このアプローチはクロスブラウザー互換であり、装飾要素の配置に柔軟性を提供し、カスタムテンプレートを使用して簡単に拡張できます。

このライブラリは、モジュール式でクロスブラウザであるため、Google Closure Toolsを使用して開発されました。これにより、追加の依存関係なしにコンパクトで高速なJavaScriptコードを生成できます。

建築

ライブラリはJavaScriptの「クラス」のコレクションとして設計されており、「クラス」アノテーターを介して必要なすべての機能をユーザーに公開します。

テキストアノテーターライブラリ

利用可能な機能の概要は次のとおりです。

  • annotateDocument-「data-annotate」属性でマークされた要素に注釈を付けます。

  • 下線-要素に下線を付ける

  • ハイライト-要素をハイライトします

  • ストライク-ストライク要素

  • underlineSelected-選択したテキストに下線を引く

  • HighlightSelected-選択したテキストを強調表示します

  • strikeSelected-選択したテキストをストライクします

  • unannotateElement-要素から注釈を削除します

  • getTemplates-注釈テンプレートの辞書を返します

  • setUnderlineOptions-アンダーラインアノテーターの設定を設定します

  • setHighlightOptions-ハイライトアノテーターの設定を設定します

  • setStrikeOptions-ストライクアノテーターの設定を設定します

annotatorクラスは、注釈関数ごとにAnnotatorImplクラスの3つのインスタンス(アンダースコア、ハイライト、およびストライク)を保持します。

 tvs.Annotator = function() { this.underliner_ = new tvs.AnnotatorImpl( 'underliner', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.underlinePositioner); this.highlighter_ = new tvs.AnnotatorImpl( 'highlighter', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.highlightPositioner, {opacity: 0.45}); this.striker_ = new tvs.AnnotatorImpl( 'striker', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.strikePositioner); };

AnnotatorImplインスタンスは、さまざまなIDとポジショナーヘルパーオブジェクトを使用して作成されます。 渡されたIDは、後でCSSクラス名と内部フィールド名で使用されるため、IDは一意である必要があります。 また、既知のテンプレートのリストへの参照が渡されます(後で変更できます)。

各ポジショナーオブジェクトは、「getPosition」メソッドのみを持つIPositionerインターフェイスの実装であり、次のようになります。

 /** * Underline positioner * @implements {tvs.IPositioner} */ tvs.AnnotatorCore.underlinePositioner = /** @type {!tvs.IPositioner} */ ({ /** * @param {Object} elementRect * @param {number} annotationHeight * @return {{left: number, top: number, width: number, height: number}} */ getPosition: function(elementRect, annotationHeight) { return { width: elementRect.width, height: annotationHeight, left: elementRect.left, top: elementRect.bottom - (elementRect.height * 0.1) }; } });

これにより、すべてのテンプレートをアンダースコア、ハイライト、またはストライクテキストの注釈とともに使用できます。 注釈が要素に適用されると、要素の境界ボックスは、以下に示すように「getElementRects」を呼び出すことによって取得されます。

 var rects = elemOrEv.getClientRects();

このメソッドは、クライアントの各ボックスの外接する長方形を示す長方形のコレクションを返します。 各長方形をコンクリートポジショナーに渡した後、目的地の境界を取得します。

SVGテキスト注釈テンプレート

前述のように、すべての種類のSVGテキスト注釈に使用されるテンプレートのセットは1つだけです。 すべてのテンプレートは、テンプレートパーツで構成されています。 テンプレートパーツは、パーツのコンテンツ、テンプレートの幅、および描画モードを表すエンティティです。

コンテンツ

コンテンツは、文字列として表されるSVG要素のセットです。 このコンテンツには、ビューポートの幅と高さ(ピクセル単位)が設定されているルートSVGノードがないため、テンプレートのパーツコンストラクターはそれらをパラメーターとして受け入れます。 たとえば、ビューポートのサイズを100px x 100pxとして指定し、(50、50)と(25、25)に線を引くことができます。 注釈が適用された後、すべてのsvg要素は適切なサイズになります。 コンテンツ値には、ユーザーが選択した色に置き換えられる文字列「{0}」を使用できます。

次のSVGは対角線をレンダリングします。 これを、注釈スタイルの例のパーツの1つとして、まもなく使用します。

 <line x1="0" y1="0" x2="5" y2="5" stroke-width="2" stroke="red" />

テンプレートの幅は、「*」、「高さ」、またはその他の文字列です。

  • 「*」は、星が互いに等しいすべての要素の幅を設定します

  • 「height」は、幅を注釈要素の高さに等しく設定します

ここで設定された他のものはすべて、CSSのwidthプロパティとmin-widthプロパティに直接設定されます。

CSSプロパティ

描画モード

描画モードは、「リピート」または「ストレッチ」のいずれかが可能な文字列です。 値が示すように、「repeat」に設定するとコンテンツが繰り返され、「stretch」に設定するとコンテンツがストレッチされます。

これらの3つのパラメーターを構成することで達成できることの例を次に示します。

テキスト注釈

上記の例のテキスト注釈には、4つの部分が含まれています。 最初の部分は対角線で、テンプレートの幅は「高さ」に設定され、描画モードは「繰り返し」に設定されています。 2番目の部分では、テンプレートの幅が「*」に設定され、描画モードが「リピート」に設定されています。 3番目の部分は、幅が「15px」に設定され、「リピート」モードで描画されます。 最後に、最後の部分の幅が「*」に設定され、その描画モードが「ストレッチ」に設定されます。

これらの幅を評価すると、最初の部分は5ピクセル(注釈要素の高さに等しい)、3番目の部分は15ピクセル(設定どおり)、残りのスペースは2番目と4番目の部分に均等に分割されます。

同じテンプレートを使用して同じテキストを強調表示すると、次のようになります。

描画モード

お分かりのように、注釈要素の高さは高く、最初の部分の幅も大きくなります(その部分のテンプレートの幅は「高さ」に設定されているため)。 当然、3番目の部分の幅は前の例から変更されていません。

同じテンプレートを使用して同じテキストに取り消し線効果を適用すると、最初のテキストと非常によく似た結果が得られます。 唯一の違いは、注釈要素が配置される場所です。

テキストanootation描画モード

これらのテキスト注釈は複雑に見えますが(見た目は4つの異なる部分があります)、すべて非常に単純なSVG要素を使用しています。 追加の例として、波線を描くには、次の単純なSVGコンテンツを含む単一の部分が必要です。

 var t = new tvs.Template(new tvs.SvgTemplatePart( '<line y2="16.00" x2="20" y1="4.00" ' + 'x1="10" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>' + '<line y2="4.00" x2="10" y1="16.00" ' + 'x1="0" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>', 20, 20, 'repeat' ))

これらのテンプレートが評価されると、コンテンツのサイズが変更され、「{0}」が指定された色に自動的に置き換えられます。 さらに、新しいテンプレートの追加は、JavaScriptオブジェクトに追加するのと同じくらい簡単です。

 tvs.AnnotatorDictionary.svgTemplates['brush'] = new tvs.Template(new tvs.SvgTemplatePart( svgContent, 50, 50, '*', 'stretch' ));

結果

各注釈は、ページに絶対位置のdiv要素を追加することによって適用されます。

 <div class="tvs-annotate-element"> <div class="tvs-wrap-div"> <table> <tr> <td></td> <td></td> <td></td> </tr> </table> </div> </div>

div要素には、追加されたすべてのセルがテンプレート内のパーツの1つに対応するテーブルが入力されます。 各テンプレートパーツのコンテンツは、選択した色が適用されたBase64エンコードデータURIとして追加されます。

 tvs.SvgTemplatePart.prototype.getBackground = function(color) { var image = tvs.AnnotatorCore.formatString(this.content, [color]); var encodedSVG = goog.crypt.base64.encodeString(image); return 'data:image/svg+xml;base64,' + encodedSVG; };

埋め込み

ユーザーエクスペリエンスを向上させるために、特に編集可能なコンテンツ領域でこのJavaScriptライブラリを使用しようとする場合、テキストアノテーターがユーザーによって現在選択されているテキストの境界を知ることが重要です。 範囲と選択を処理するきちんとしたJavaScriptライブラリであるRangyは、クロスブラウザ方式でこれを実現するために使用されています。 Rangyは、すべての主要なブラウザーで共通のDOM範囲および選択タスクを実行するための単純な標準ベースのAPIを提供し、InternetExplorerからDOM準拠のブラウザーまでのこの機能の大きく異なる実装を抽象化します。 これは、プロジェクトの唯一の依存関係です。

Text Annotatorが埋め込まれると、それを使用するのは非常に簡単なことです。

 var annotator = new tvs.Annotator(); annotator.underlineSelected();

各注釈付き要素は「tvs-annotated-text」クラスでマークされ、各注釈要素には「tvs-annotate-element」クラスがあります。 注釈の削除はさらに簡単で、ワンライナーです。

 annotator.unannotateElement(annotatedElement);

ウィンドウのサイズが変更されると、要素が移動する可能性があり、注釈付きの要素を「更新」する必要があります。 これはライブラリによって処理されます。 しかし; パフォーマンスへの影響を減らすために、注釈の更新の呼び出しは抑制されます。

 tvs.AnnotatorImpl = function(id, templates, positioner, options) { // ... this.throttle = new goog.Throttle(goog.bind(this.refreshAllAnnotations, this), 50); tvs.AnnotatorCore.registerForWindowResize( this.id,goog.bind(this.throttle.fire, this.throttle)); }; tvs.AnnotatorImpl.prototype.refreshAllAnnotations = function() { var elems = goog.dom.getElementsByClass(this.getCssClassForAnnotated()); var refFunc = goog.bind(this.refreshAnnotation, this); goog.array.forEach(elems, refFunc); };

更新時に、必要に応じて注釈要素をページに追加、サイズ変更、またはページから削除できます。

快適

ページ上の静的テキストに注釈を付けるのを簡単にするために必要なのは、container要素の単純なデータ属性だけです。

 data-annotate='underline squiggly green'

これにより、要素のコンテンツに波状の緑色の下線が付けられます。

結論

このSVGテキストチュートリアルについてこれ以上何が言えますか? 楽しくて強力なツールが簡単に実装されています。 Internet Explorer 8のサポートを確保しても、実装全体が複雑になる可能性があるため、あまりメリットはないと思います。 ただし、いくつかの改善とコアの少しの作業により、ライブラリを拡張して、非テキスト要素の装飾的な境界線を作成できるようになります。 さらに、注釈の編集可能なコンテンツの状態を保存して後で復元するためのメカニズムを実装することは、興味深いタスクになる可能性があります。

今のところ、可能性はあなたの想像力(そしてブラウザの能力)によってのみ制限されます。 おそらく、マイクロプリントの線、グラデーション、さらにはアニメーションが必要です。 テキストアノテーターを使用すると、次のことができます。