enpitsulin

enpitsulin

这个人很懒,没有留下什么🤡
twitter
github
bilibili
nintendo switch
mastodon

Openlayers 中将图层裁切

一般的に、GIS サービスから取得したタイルマップを使用して地図を描画する場合、行政区域の形状がデザインに合わせて切り抜かれていることがあります。ただし、提供されたサービスでこの形状を変更することができない場合、フロントエンドで地図を切り抜いて加工する必要があります。

通常、行政区域の形状は GIS サービスから取得するか、静的な GeoJSON リソースから面要素データを取得することができます。必要な形状を切り抜くために、面要素データを使用しますが、OpenLayers にはこれを完了するための組み込みの API はありません。この場合、globalCompositeOperationを使用するためにキャンバスを使用する必要があります。

まず、レイヤーが WebGL レイヤーではないことを確認し、切り抜く対象となる基本レイヤーbaseLayerを定義する必要があります。

import { Tile } from 'ol/layer'
import { XYZ } from 'ol/source'
const baseLayer = new Tile({
  source: new XYZ({
    url: `sourceUrl`,
  }),
})

もちろん、このレイヤーはタイルマップである必要はありませんが、ほとんどのビジネスではそれが主要なものです。

切り抜き範囲の取得#

次に、切り抜く面要素データを使用してVectorレイヤーを作成し、そのソースのaddFeatureイベントをバインドして基本レイヤーの可視範囲をclipLayerと同じにします。

import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import EsriJson from 'ol/format/EsriJSON';
const clipLayer = new VectorLayer({
  source: new VectorSource({
    url: `提供面要素服务地址`,
    format: new EsriJson() // ここでGISサービスがEsriJson形式であるため、GeoJsonやその他の形式を使用する場合は対応するフォーマットを使用します
  });
});

clipLayer.getSource().on('addfeature', ()=> {
  baseLayer.setExtent(clipLayer.getSource().getExtent());
});

これにより、基本レイヤーは切り抜き範囲内のタイルのみをロードするようになります。次に、境界を切り抜く必要があります。

ここで、レイヤーのpostrenderイベントを使用します。これは、タイルのレンダリングが完了したがフェードインされていない状態で発生するイベントです。このイベントを使用して、キャンバスのglobalCompositeOperationを設定することで、切り抜き効果を得ることができます。

baseLayer.on('postrender', (evt) => {
  if (!evt.context || !('save' in evt.context)) return
  const vecCtx = getVectorContext(evt)
  evt.context.globalCompositeOperation = 'destination-in'
  clipLayer.getSource().forEachFeature((feature) => {
    vecCtx.drawFeature(feature, style)
  })
  evt.context.globalCompositeOperation = 'source-over'
})

globalCompositeOperationdestination-inに設定すると、キャンバスはキャンバスの内容と重なる部分のみを描画し、他の部分は透明になります。同時に、getVectorContext(evt)またはbaseLayerを使用して要素を再描画することで、切り抜かれたタイルマップを取得できます。

静的なコンテンツから切り抜き範囲を取得#

ファイルから取得する場合、VectorLayerの構築パラメーターの url を features に変更し、ファイルから features を読み取るために format を使用します。

const clipLayer = new VectorLayer({
  source: new VectorSource({
    features: [new EsriJson().readFeatures(require('パス'))],//formatはサービスと同じです
  });
});
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。