色別標高図 + 注記

地理院タイルの色別標高図に傾斜量図を乗算合成したベースマップに、最適化ベクトルタイルの注記レイヤーから地形の名称、水域の名称、地名を抜き出して描写した例です。

Example code

import Tile from 'ol/layer/Tile';
import LayerGroup from 'ol/layer/Group';
import XYZ from 'ol/source/XYZ';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
import Text from 'ol/style/Text';
import {
  gsiOptVtLayer,
  annoCodeIsElevation,
  annoCodeIsTerrain,
  annoCodeIsWater,
  zoomToResolution,
  type GsiOptVTFeatureProperties,
} from '@cieloazul310/ol-gsi-vt';

const relief = new Tile({
  source: new XYZ({
    url: 'https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png',
    attributions:
      '<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">地理院タイル</a>',
    maxZoom: 15,
    minZoom: 5,
  }),
});
const slope = new Tile({
  className: 'multiply',
  source: new XYZ({
    url: 'https://cyberjapandata.gsi.go.jp/xyz/slopemap/{z}/{x}/{y}.png',
    attributions:
      '<a href="https://maps.gsi.go.jp/development/ichiran.html" target="_blank">地理院タイル</a>',
    maxZoom: 15,
    minZoom: 3,
  }),
});

const anno = gsiOptVtLayer({
  layers: ['AdmBdry', 'Anno', 'WA', 'RvrCL', 'WRltLine'],
  background: false,
  theme: {
    palette: {
      boundary: { main: '#000' },
      searoute: '#02a',
    },
  },
  styles: {
    Anno: (feature, resolution, theme) => {
      const { vt_code, vt_text } =
        feature.getProperties() as GsiOptVTFeatureProperties<
          number,
          {
            vt_text?: string;
          }
        >;
      if (!vt_text) return new Style();
      if (annoCodeIsTerrain(vt_code)) {
        const order =
          vt_code === 333 ? 3 : [313, 316, 332, 832].includes(vt_code) ? 1 : 2;
        const fontSize = order === 3 ? 'xl' : order === 2 ? 'lg' : 'md';
        return new Style({
          text: new Text({
            text: vt_text,
            font: theme.typography.toString(fontSize, { bold: true }),
            fill: new Fill({ color: theme.palette.contrast }),
            stroke: new Stroke({
              color: theme.palette.anno.terrain,
              width: 4,
            }),
          }),
          zIndex: theme.zIndex.label + order,
        });
      }
      if (annoCodeIsWater(vt_code)) {
        const order = [341, 344, 348, 840, 841].includes(vt_code)
          ? 2
          : [321, 322, 345, 347, 521, 820, 842].includes(vt_code)
          ? 1
          : 0;
        const fontSize = order === 2 ? 'xl' : order === 1 ? 'lg' : 'md';
        return new Style({
          text: new Text({
            text: vt_text,
            font: theme.typography.toString(fontSize, { bold: true }),
            fill: new Fill({ color: theme.palette.contrast }),
            stroke: new Stroke({
              color: theme.palette.anno.water,
              width: 4,
            }),
          }),
          zIndex: theme.zIndex.label + order,
        });
      }
      if ([110, 140, 210].includes(vt_code)) {
        const order = vt_code === 140 ? 4 : vt_code === 110 ? 2 : 0;
        const fontSize =
          order === 4 && resolution < zoomToResolution(9)
            ? 'xl'
            : order === 2
            ? 'lg'
            : 'md';
        return new Style({
          text: new Text({
            text: vt_text,
            font: theme.typography.toString(fontSize),
            fill: new Fill({ color: theme.palette.contrast }),
            stroke: new Stroke({
              color: theme.palette.anno.text.main,
              width: 4,
            }),
          }),
          zIndex: theme.zIndex.label + order,
        });
      }
      if (!annoCodeIsElevation(vt_code)) return new Style();
    },
    WA: (feature) => {
      const { vt_code } = feature.getProperties() as GsiOptVTFeatureProperties;
      if ([5100, 5101, 5102, 5103, 5111, 5121].includes(vt_code))
        return new Style();
    },
  },
});

const layer = new LayerGroup({
  layers: [relief, slope, anno],
});

export default layer;
/** style.css */
.multiply {
  mix-blend-mode: multiply;
}

ol-gsi-vt