ホームページ > 記事 > ウェブフロントエンド > フロントエンドアルゴリズムにおけるテキスト回避に関連する問題 (詳細なチュートリアル)
この記事では、主にフロントエンド アルゴリズムのテキスト回避に関する関連情報を紹介します。多くの友人はこの知識を知らないと思いますが、inMap のテキスト回避機能の主な使用方法を見ると驚かれるでしょう。この効果を実現するには、この記事でサンプルコードを通して詳しく紹介していますので、必要な方は参考にしてください。
はじめに
inMap は、キャンバスに基づいたビッグデータ視覚化ライブラリであり、ビッグデータの方向の点、線、および面の視覚的な表示に焦点を当てています。現在、スキャッター、フェンス、サーマル、グリッド、集計などの手法をサポートしており、ビッグ データの視覚化をシンプルかつ使いやすくすることに取り組んでいます。
GitHub アドレス: https://github.com/TalkingData/inmap (ローカル ダウンロード)
ドキュメント アドレス: http://inmap.talkingdata.com/
地理情報の視覚化では、要件を満たすために地図に遭遇することがよくありますテキストをマークする際の、一般的なグラフ フレームの効果を以下に示します。
テキストを表示するための十分なスペースがない場合、テキストが重なって表示がわかりにくくなり、ユーザー エクスペリエンスが非常に不親切になります。
この問題を解決するにはどうすればよいですか?この不正行為の問題を解決するために、テキスト回避アルゴリズムを使用します。
以下は、inMap のテキスト回避効果を示しています:
テキスト注釈アルゴリズムは、GIS で最も複雑な問題の 1 つです (これは NP の複雑さの問題であるため、通常、最適な解決策は見つかりません。ほどいた方が良いです)。
inMap 回避アルゴリズムは四分位モデル アルゴリズムを使用します。次に、経験豊富なドライバーが回避アルゴリズムを作成する方法を段階的に説明します。
データを準備します
inMap は緯度と経度のデータを受け取り、それをキャンバスのピクセル座標にマッピングする必要があります。メルカトル変換は将来的には非常に複雑になります。 . この記事では彼の原則について説明します。変換後、取得するデータは次のようになります:[ { "name": "海门",//要显示的文字 "lng": 121.15, "lat": 31.89, "count": 7, "pixel": { //像素坐标 "x": 968, "y": 736 } }, { "name": "鄂尔多斯", "lng": 109.781327, "lat": 39.608266, "count": 5, "pixel": { "x": 659, "y": 478 } }, ... ]さて、変換されたピクセル座標データ (x, y) が得られたので、次のことができます。
各テキスト四角形の実際のサイズを確認します
measureText() は、フォント幅のピクセル単位を返す Canvas の組み込みメソッドです:let ctx = this.container.getContext('2d'); // canvas 上下文 let width= ctx.measureText(name).width;measureText を通じて各テキストの幅を取得します、キャンバスは直接テキストを取得する方法、テキストの高さを取得する方法はありませんか? キャンバスフォントが「13px Arial」フォントと等しい場合(他のフォントは保証できません)、テキストの高さはfontSizeの約1.1倍になることが、繰り返しのテストにより判明しました。 したがって、コードは次のようになります:
let fontSize = parseInt(ctx.font); let height = fontSize * 1.1;テキストの幅と高さを取得した後、テキスト四角形の座標系を作成できます。
四分位モデルを作成する
いわゆる四分位モデル。マークされた各ポイントには、テキスト用に上下左右の 4 つの位置があります。左側に配置できない場合は、配置してみてください。それがうまくいかない場合は、以下を試してください、というように、原理は単純です(笑)。 右側の仮想長方形の座標の説明を作成します: 右側の仮想長方形の座標の説明には、テキストとドットが重ならないようにドットも含まれています。 仮想長方形の高さを計算する際にはいくつかの落とし穴があります。ドットのサイズは固定されておらず、ユーザーに応じて動的に設定されます。仮想長方形の高さを常に最大にするためには、特別な処理が必要です。 コードは次のとおりです:_getLeftAnchor() { let x = this.center.x - this.radius - this.textReact.width, y = this.center.y - this.textReact.height / 2, diam = this.radius * 2, maxH = diam > this.textReact.height ? diam : this.textReact.height; //矩形的高度 return { x, y, minX: x, maxX: this.center.x + this.radius, minY: this.center.y - maxH / 2, maxY: this.center.y + maxH / 2 }; }など、下、左、上の仮想四角形の座標を記述します。
衝突判定
2 つの長方形が重なっているか交差しているかを判定します。その長方形の minX、maxX、minY、maxY に基づいて交差を判定します。 原理は次のとおりです。/** * 判断分位是否相交 * @param {*} target */ isAnchorMeet(target) { let react = this.getCurrentRect(), targetReact = target.getCurrentRect(); if ((react.minX < targetReact.maxX) && (targetReact.minX < react.maxX) && (react.minY < targetReact.maxY) && (targetReact.minY < react.maxY)) { return true; } return false; }
仮想テキスト コレクション オブジェクトを作成します
let labels = pixels.map((val) => { let radius = val.pixel.radius + this.style.normal.borderWidth; //圆点半径 return new Label(val.pixel.x, val.pixel.y, radius, fontSize, byteWidth, val.name); });仮想テキスト コレクションを再帰的に走査して、他のテキスト コレクションと交差するかどうかを判断します。交差する場合は、交差しなくなるまで現在のテキストの位置を移動します。適切な場所が見つからない場合は、現在のテキストを非表示にすることを選択します。 コードは次のとおりです:
do { var meet = false; //本轮是否有相交 for (let i = 0; i < labels.length; i++) { let temp = labels[i]; for (let j = 0; j < labels.length; j++) { if (i != j && temp.show && temp.isAnchorMeet(labels[j])) { temp.next(); meet = true; break; } } } } while (meet);
テキストの描画
labels.forEach(function (item) { if (item.show) { //是否显示 let pixel = item.getCurrentRect(); ctx.beginPath(); ctx.fillText(item.text, pixel.x, pixel.y); ctx.fill(); } });テキスト回避アルゴリズムはこれまでに導入されています。対応する inMap ファイルのアドレスは https://github.com/TalkingData/inmap/blob/ です。 master/src/worker /helper/Label.js 、今後も有益な情報を共有していきます。 上記は私があなたのためにまとめたものです。 関連記事:
express+multerで画像アップロード機能を実装する方法
WeChatミニプログラムでYDUIのScrollTabコンポーネントを使用する方法
以上がフロントエンドアルゴリズムにおけるテキスト回避に関連する問題 (詳細なチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。