メインコンテンツまでスキップ

チュートリアル13 WebApp Layer WMS 伸縮スクロールに応じた表示

はじめに

WebApp Layer機構を用いれば、ウェブサービスに接続し表示領域に応じた地図コンテンツを動的に表示することができます。チュートリアル12と同じGEBCO Web Serviceを使ってみます。

  • 実際の動作は、wms2.html をクリック。
    • Note: WMSが地図を生成配信するまでに少々時間がかかります)

ソースコードディレクトリ

  • ソースコードのディレクトリ
  • 表示領域のパラメータを伸縮スクロールの度に取得します。
  • このパラメータを用いて、WMSへのクエリURLを構築します。
  • image要素によって、WMSから取得したデータを配置します
  • 1ステップ前のimage要素は消去します。

チュートリアル

WMS (Web Map Service)を使って、表示している領域の地図を伸縮スクロールに応じて表示する機能を持つレイヤーをWebApp Layerとして実装します。WMSとしてはTutorial 12 に引き続き the GEBCO Web Serviceを使用します。

wms2.html

これまでと特に変わったところはありません。

Container.svg

これまでと特に変わったところはありません。

wms_dynamic.svg

  • data-controller="wmsController.html" このレイヤーにWebApp("wmsController.html)を紐付けています
    • WebAppではWMSのコンテンツを表示するためのDOM操作を伸縮スクロールのたびに行っています。
  • image要素はダミーです(xlink:href属性がないので表示されない)
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="120,-50,30,30" data-controller="wmsController.html#exec=appearOnLayerLoad">
<globalCoordinateSystem srsName="http://purl.org/crs/84" transform="matrix(1,0,0,-1,0,0)"/>
<image id="wmsImage" preserveAspectRatio="none" opacity="0.5" />
</svg>

wmsController.html, wmsController.js

  • onload webApp読み込み直後に呼ばれる関数
    • svgMap.refreshScreen() webAppが読み込まれた直後に地図の[[[解説書#refreshScreen|再描画を明示]]し、 preRenderFunctionが実行されるようにします。
  • preRenderFunction 再描画に際して実行されるコールバック関数です。伸縮スクロール時も再描画されるため呼び出されます。
    • prevImageElement.remove() 1ステップ前(伸縮スクロールが起きる直前)のWMSからの画像を消去
    • svgMap.getGeoViewBox() 表示領域を地理座標で取得
    • getScreenSize() 地図表示画面のサイズを取得
    • getWMSreq(GEBCOurl, GEBCOlayer, geoViewBox, screenSize)
      • 表示領域、スクリーンサイズなどのパラメータをもとにGEBCO WMSへのリクエストURLを生成する関数
      • クエリパラメータの設定内容については、 チュートリアル12のWMSに関する説明を参照
    • getSvgImage(req, geoViewBox) 上で生成したWMSへのリクエストURIと、その地図データの領域情報をもとに、image要素を生成する関数
    • svgImage.documentElement.appendChild(newImage) 生成したImage要素をSVGコンテンツに設置

wmsController.js

onload=function(){
svgMap.refreshScreen();
}

var GEBCOurl="https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv";
var GEBCOlayer="GEBCO_LATEST";

var crsAD=1;

function preRenderFunction(){
var prevImageElement = svgImage.getElementById("wmsImage");
prevImageElement.remove();

var geoViewBox = svgMap.getGeoViewBox();
var screenSize = getScreenSize();
var req = getWMSreq(GEBCOurl, GEBCOlayer, geoViewBox, screenSize);

var newImage = getSvgImage(req, geoViewBox);
svgImage.documentElement.appendChild(newImage);
}

function getSvgImage( imageUrl, geoViewBox){
var imageElement = svgImage.createElement("image");
imageElement.setAttribute("opacity", 0.5);
imageElement.setAttribute("preserveAspectRatio", "none");
imageElement.setAttribute("id", "wmsImage");
imageElement.setAttribute("xlink:href", imageUrl);
imageElement.setAttribute("x", geoViewBox.x * crsAD);
imageElement.setAttribute("y", -(geoViewBox.y+geoViewBox.height) * crsAD); // 軸反転のため北端を設定
imageElement.setAttribute("width", geoViewBox.width * crsAD);
imageElement.setAttribute("height", geoViewBox.height * crsAD);
return(imageElement);
}

function getWMSreq(baseUrl, layerName, geoArea, screenSize){
var wmsArea_x0=geoArea.x;
var wmsArea_y0=geoArea.y;
var wmsArea_x1=geoArea.x+geoArea.width;
var wmsArea_y1=geoArea.y+geoArea.height;

var ans = `${baseUrl}?
request=GetMap&
service=WMS&
version=1.1.1&
layers=${layerName}&
srs=EPSG:4326&
bbox=${wmsArea_x0},${wmsArea_y0},${wmsArea_x1},${wmsArea_y1}&
width=${screenSize.width}&
height=${screenSize.height}&
format=image%2Fpng`;

ans = ans.replace(/\s/g,""); // 空白文字(改行含)を除去
return ( ans );
}

function getScreenSize(){
var gvb = svgMap.getGeoViewBox();
var scale = svgImageProps.scale;
return {
width : Math.round(gvb.width * scale),
height: Math.round(gvb.height * scale),
}
}