enpitsulin

enpitsulin

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

Openlayers 中将图层裁切

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

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

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

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

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

GIS サービスから切り取り範囲を取得#

次に、切り取りの面要素データを使用して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イベントを使用します。これは、タイルのレンダリングが完了したが、フェードインがロードされていない状態で発生するイベントです。このイベントを使用して、canvas の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に設定されている場合、canvas はキャンバスの内容と重なる部分のみを描画し、他の部分は透明に保ちます。同時に、getVectorContext(evt)またはbaseLayerを使用して要素を再描画することで、切り取り後のタイル地図を取得できます。

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

ファイルから取得する場合は、VectorLayerの構築パラメータの url を features に変更し、フォーマットを使用してファイルから features を読み取るだけです。

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