banner
陈不易

陈不易

没有技术想聊生活
twitter
medium
tg_channel

矢量タイルのハイライト選択 Openlayers[1]

自分で作った小さなデモにこんな小さな要件があります:データベースを通じて、指定された属性の要素を取得し、それをハイライト表示することです。

WFS の通常の方法で読み込む場合は問題ありませんが、layerfeature sourceを遍歴するだけで済みます。効率は考慮せず、論理的には問題ありませんが、要件としてレイヤーのfeatureが非常に多い(世界中の海岸線から生成されたバッファーのため)ため、地図の読み込みの過程でベクタタイルの形式を使用しました。ベクタタイルタイプのsourceにはgetFeatures()メソッドがないため、ハイライト表示が必要な要素を遍歴するのが面倒になりました。

レイヤーの静的スタイルはopenlayersの最新の例の方法で設定されています:

//カラーテーブル
const colorTable = {
  "No": "rgba(200, 54, 54, 0)",
  "type1": "#FF0000",
  "type2": "#E69800",
  ...
  "": "#00FFFFFF",
};
export function createRiskLevelStyle(feature) {

  const riskLevel = feature.get('props_X');
  let selected = !!selection[feature.getId()];
  return new Style({
    fill: new Fill({
      //color: colorTable[riskLevel],
      color: selected ? 'rgba(200,20,20,0.8)' : colorTable[riskLevel],
      //color: 
    }),
    stroke: new Stroke({
      color: '#FFFFFF',
      width: 0.1,
    })
  })
}

ここでselectedはマウスクリックによるハイライト表示に使用され、論理的にはクリック後にfeatureidをキーとして保存し、その要素が選択されたことを示します。

当然、この要件を考慮する際、最初に思いついたのはfeatureCollectionを遍歴して対応する要素のIdを見つけ、selectionというグローバル変数に保存することでした。しかし、ベクタタイルのsourceにはgetFeatures()メソッドがないため、このアイデアは破綻しました。その後、データを遍歴するために普通の WFS レイヤーを新たに作成しようとも考えましたが、データ量が非常に大きく、一度の読み込みで 50MB 以上かかるため、この方法も完全に破綻しました。

その後、読み込み時にスタイルをこの形式のstyleFuncで使用できるので、検索時にレイヤーに新しいFuncを割り当てることで効果があるのではないか、性能はどうかと考えました。そこでstyleFunを微調整した結果は以下の通りです:

export function createRiskLevelStyleSearch(names) {
  return function (feature) {
    const riskLevel = feature.get('props_X');
    let properties = feature.getProperties();
    let zh = properties['label'];
    let en = properties['name'];
    let searched = false;
    if (zh === undefined || en === undefined) {
      searched = false;
    } else {
      names.forEach((v) => {
        if (en === v.key)
          searched = true;
      });
    }
    return new Style({
      fill: new Fill({
        //color: colorTable[riskLevel],
        color: searched ? 'rgba(200,20,20,0.8)' : colorTable[riskLevel],
        //color:
      }),
      stroke: new Stroke({
        color: '#FFFFFF',
        width: 0.1,
      })
    });
  }

}

パラメータnamesは国名の配列で、itemkeyは検索する値に対応しています。

この方法はこのデータ量の下で、効果はまずまずです。以下の図のように:

image

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。