チュートリアル15

提供: svg2wiki
(版間での差分)
移動: 案内, 検索
(REST API)
(CanadianGeoNames.html)
37行: 37行:
 
* num 出力する最大数
 
* num 出力する最大数
  
*クロスオリジン設定
+
*クロスオリジン設定 今回は別ドメインのサービスにアクセスすることになるので、ウェブサービスがクロスオリジンアクセスを許可している必要があります。[https://www.nrcan.gc.ca/maps-tools-and-publications/maps/geographical-names-canada/application-programming-interface-api/9249 Geographical names in Canada : Geoname Service]は許可されているようです。
  
 +
====配信されるデータ====
 +
クエリパラメータに基づいたCSVデータが変身されます。
  
 
*geoJsonExample2.svgに紐付けられ、[[解説書#.E3.83.AC.E3.82.A4.E3.83.A4.E3.83.BC.E5.9B.BA.E6.9C.89.E3.81.AEUI|そのDOMをコントロールできるwebApp]]
 
*geoJsonExample2.svgに紐付けられ、[[解説書#.E3.83.AC.E3.82.A4.E3.83.A4.E3.83.BC.E5.9B.BA.E6.9C.89.E3.81.AEUI|そのDOMをコントロールできるwebApp]]

2022年2月28日 (月) 07:10時点における版

目次

チュートリアル15 WebApp Layer 伸縮スクロールに応じたベクトル地理情報サービス結合

動的にベクトルデータが生成・配信されているサービスをSVGMap.jsに結合します。チュートリアル14に対して、こちらは伸縮スクロールする度にその表示領域に応じたデータをサービスから取得して表示します。またチュートリアル14はgeoJsonデータのサービスでしたがこちらはCSVデータです。

結合するサービスはNatural Resources Canadaが提供している、Geoname Service API(カナダの地名データサービス)です。

vectorService1.html

Container.svg

CanadianGeoNames.svg

  • チュートリアル14と特に違いはありません。アイコンの色もこちらは赤に固定しています。
<?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="CanadianGeoNames.html#exec=appearOnLayerLoad">
 <globalCoordinateSystem srsName="http://purl.org/crs/84" transform="matrix(1,0,0,-1,0,0)"/>
 <defs>
 <g id="p0">
   <circle cx="0" cy="0" r="6" fill="red"/>
 </g>
 </defs>
</svg>

CanadianGeoNames.html

REST API

少し複雑ですので、Geographical names in Canada : Geoname Serviceが提供するAPIのうち今回使用する部分をまとめます。

使用するクエリパラメータ

今回は以下の二つを使います。

  • bbox 西、南、東、北の座標(世界測地系の度の値)をカンマ区切りで指定
  • num 出力する最大数
  • クロスオリジン設定 今回は別ドメインのサービスにアクセスすることになるので、ウェブサービスがクロスオリジンアクセスを許可している必要があります。Geographical names in Canada : Geoname Serviceは許可されているようです。

配信されるデータ

クエリパラメータに基づいたCSVデータが変身されます。

  • geoJsonExample2.svgに紐付けられ、そのDOMをコントロールできるwebApp
  • チュートリアル6#geoJsonExample1.htmlに対して以下が相違点
  • addEventListener("load", function(){..})
    • changeData() UIの設定に基づき、地震データをリクエストして可視化する関数
      • getUSGSURL() USGSが配信する地震データを取得するためのGETリクエストを生成
      • loadAndDrawGeoJson()
    • setInterval(function(){..}..) 指定した間隔で定期的に更新する関数(地震データはリアルタイムに更新されるため)
<!doctype html>
<html>
<head>
<title>basic dynamic wms layer controller</title>
<meta charset="utf-8"></meta>
</head>
<script>

var canadianGeoNamesService = "https://geogratis.gc.ca/services/geoname/en/geonames.csv";

onload=function(){
	addEventListener("zoomPanMap", async function(){
		geoNames = await getGeoNames();
	});
	getGeoNames();
}


var crsAD=1;
var maxItems=100;

async function getGeoNames(){
	console.log("called getGeoNames");
	
	var geoViewBox = svgMap.getGeoViewBox();
	var req = getCanadianGeoNamesReq(geoViewBox);
	var csv = await getCsv(req);
	if ( csv.length > maxItems){
		messageDiv.innerText="Exceeded maximum number. Please zoom in.";
	}else{
		messageDiv.innerText="";
	}
	drawPoints(csv);
	console.log(csv);
}

function getCanadianGeoNamesReq(geoArea){
	var area_x0=geoArea.x;
	var area_y0=geoArea.y;
	var area_x1=geoArea.x+geoArea.width;
	var area_y1=geoArea.y+geoArea.height;
	var ans = `${canadianGeoNamesService}?bbox=${area_x0},${area_y0},${area_x1},${area_y1}&num=${maxItems}`;
	return ( ans );
}

async function getCsv(url){
	var response = await fetch(url); 
	var txt = await response.text();
	txt = txt.split("\n");
	var ans = [];
	for ( var line of txt ){
		// https://www.ipentec.com/document/csharp-read-csv-file-by-regex ダブルクォーテーションエスケープを加味したcsvパース
		line = line.split(/,(?=(?:[^"]*"[^"]*")*[^"]*$)/);
		if (line.length > 1){
			ans.push(line);
		}
	}
	return ( ans );
}

function drawPoints(csv){
	removeUses();
	var schema = csv[0].join();
	var latCol=csv[0].indexOf("latitude");
	var lngCol=csv[0].indexOf("longitude");
	svgImage.documentElement.setAttribute("property",schema);
	for ( var i = 1 ; i < csv.length ; i++){
		var point = csv[i];
		var meta = point.join();
		var lat = Number(point[latCol]);
		var lng = Number(point[lngCol]);
		var use=svgImage.createElement("use");
		use.setAttribute("xlink:href","#p0");
		use.setAttribute("content",meta);
		use.setAttribute("x",0);
		use.setAttribute("y",0);
		use.setAttribute("transform",`ref(svg,${lng},${-lat})`);
		svgImage.documentElement.appendChild(use);
	}
	svgMap.refreshScreen();
}

function removeUses(){
	var uses = svgImage.getElementsByTagName("use");
	console.log(uses.length);
	for ( var i = uses.length-1 ; i >=0 ; i--){
		uses[i].remove();
	}
	
	console.log(svgImage.getElementsByTagName("use").length);
}
</script>
<body>
<h3>Canadian GeoNames layer controller</h3>
<p>Get CanadianGeoNames Features from <a href="https://www.nrcan.gc.ca/maps-tools-and-publications/maps/geographical-names-canada/application-programming-interface-api/9249" target="_blank">Canadian GeoNames Search Service</a></p>
<div id="messageDiv" style="color:red">-</div>
</body>
</html>
個人用ツール
名前空間

変種
操作
案内
ツール
Translate