チュートリアル7

提供: svg2wiki
(版間での差分)
移動: 案内, 検索
(ページの作成:「=チュートリアル7 WebApp Layer ベクトルタイル= 実際の動作は、[https://svgmap.org/devinfo/devkddi/tutorials/tiling1/tiling1.html こちら]をクリッ...」)
 
1行: 1行:
 
=チュートリアル7 WebApp Layer ベクトルタイル=
 
=チュートリアル7 WebApp Layer ベクトルタイル=
 
実際の動作は、[https://svgmap.org/devinfo/devkddi/tutorials/tiling1/tiling1.html こちら]をクリック。
 
実際の動作は、[https://svgmap.org/devinfo/devkddi/tutorials/tiling1/tiling1.html こちら]をクリック。
 +
  
 
==tiling1.html==
 
==tiling1.html==
98行: 99行:
 
**<code>getTileList(geoViewBox)</code>:表示すべきタイルをリストアップする
 
**<code>getTileList(geoViewBox)</code>:表示すべきタイルをリストアップする
 
**<code>delete tiles[tileKey]</code>表示領域から外れたタイルのグループを消去
 
**<code>delete tiles[tileKey]</code>表示領域から外れたタイルのグループを消去
**<code>drawTiles()</code>: 既に表示済みのものを除き、表示すべきデータを読み込み表示する
+
**<code>await loadCSV()</code>: 既に読み込み済みのものを除き、表示すべきタイルデータ(CSV)を読み込み
 +
**<code>drawTiles()</code>:読み込んだCSVデータを表示する
 
***タイルを表示するためのグループを作成
 
***タイルを表示するためのグループを作成
***
+
***<code>csv2geojson</code>: 読み込んだCSVからgeoJsonを生成する
 +
***<code>svgMapGIStool.drawGeoJson()</code>: geoJsonからSVGのDOMを生成
 +
<pre>
 +
<!doctype html>
 +
<html>
 +
<head>
 +
<title>Simple Tiling Tutorial</title>
 +
<meta charset="utf-8"></meta>
 +
</head>
 +
 
 +
<script>
 +
 
 +
addEventListener("load",init);
 +
addEventListener("zoomPanMap",zpmFunc);
 +
 
 +
var latCol=10;
 +
var lngCol=9;
 +
var tilesTh=8; // 画面の中に入るタイルの枚数の閾値(縮小すると読み込むタイルが多くなりすぎ重くなるのを防ぐ)
 +
 
 +
function init(){
 +
zpmFunc();
 +
}
 +
 
 +
function getTileList(geoViewBox){
 +
var tileNames={};
 +
for ( var ty = Math.floor(geoViewBox.y) ; ty<= Math.floor(geoViewBox.y+geoViewBox.height) ; ty++){
 +
for ( var tx = Math.floor(geoViewBox.x) ; tx <= Math.floor(geoViewBox.x+geoViewBox.width) ; tx++){
 +
var tile="tile_" + tx + "_" + ty;
 +
tileNames[tile]=true;
 +
}
 +
}
 +
return ( tileNames);
 +
}
 +
 
 +
var tiles={}; // データ(CSVを配列化したもの)をタイルごとに格納する変数
 +
 
 +
async function zpmFunc(){
 +
var geoViewBox = svgMap.getGeoViewBox();
 +
var tileList=getTileList(geoViewBox);
 +
 +
if (Object.keys(tileList).length < tilesTh ){
 +
for ( var tileKey in tiles ){ // 必要ないデータを消す
 +
if ( !tileList[tileKey]){
 +
delete tiles[tileKey];
 +
}
 +
}
 +
for ( var tileKey in tileList ){ // 不足しているデータを読み込む
 +
if ( !tiles[tileKey] ){
 +
tiles[tileKey]=await loadCSV(`tiles/${tileKey}.csv`); // テンプレートリテラル
 +
}
 +
}
 +
message.innerText="-";
 +
drawTiles(tileList);
 +
} else {
 +
message.innerText="Too many tiles, please zoom in.";
 +
removeAllTiles();
 +
}
 +
}
 +
 
 +
function removeAllTiles(){
 +
tiles={};
 +
var groups = svgImage.getElementById("mapTiles").children;
 +
for ( var i = groups.length -1 ; i >= 0 ; i-- ){
 +
groups[i].remove();
 +
}
 +
svgMap.refreshScreen();
 +
}
 +
 
 +
function drawTiles(tileList){
 +
// tileList:表示すべきタイルのキー(ID)の連想配列
 +
var tileGroup = svgImage.getElementById("mapTiles");
 +
var groups = tileGroup.children;
 +
for ( var i = groups.length -1 ; i >= 0 ; i-- ){
 +
var groupKey = groups[i].getAttribute("id");
 +
if ( !tileList[groupKey]){
 +
groups[i].remove(); // 表示する必要のないグループは消す
 +
} else {
 +
delete tileList[groupKey]; // すでに描画済みのタイルなのでtileListから消す
 +
}
 +
}
 +
// tileListは、新たに描画すべきタイルのリストとなった
 +
for ( var tileKey in tileList){
 +
var grp = svgImage.createElement("g");
 +
grp.setAttribute("id",tileKey);
 +
tileGroup.appendChild(grp);
 +
if ( tiles[tileKey] ){
 +
var geoJson = csv2geojson(tiles[tileKey], lngCol, latCol);
 +
svgMapGIStool.drawGeoJson(geoJson, layerID, "", 0, "", "p0", "poi", "", grp);
 +
}
 +
 +
}
 +
svgMap.refreshScreen();
 +
}
 +
 
 +
var schema;
 +
 
 +
async function loadCSV(url){
 +
var response = await fetch(url);
 +
if ( response.ok ){
 +
var txt = await response.text();
 +
txt=txt.split("\n");
 +
var csv=[];
 +
var schemaLine = true;
 +
for ( line of txt){
 +
line = line.trim();
 +
if ( schemaLine ){
 +
schema = line;
 +
svgImage.documentElement.setAttribute("property",schema);
 +
} else {
 +
if ( line !=""){
 +
line=line.split(",");
 +
csv.push(line);
 +
}
 +
}
 +
schemaLine = false;
 +
}
 +
return ( csv );
 +
} else {
 +
return ( null );
 +
}
 +
}
 +
 
 +
function csv2geojson(csvArray, lngCol, latCol){
 +
var geoJson = {type: "FeatureCollection",  features: []}
 +
for ( var csvRecord of csvArray ){
 +
var lng = Number(csvRecord[lngCol]);
 +
var lat = Number(csvRecord[latCol]);
 +
var feature = { type: "Feature",
 +
geometry: {
 +
type: "Point",
 +
"coordinates": [lng, lat]
 +
},
 +
"properties": {
 +
"csvMetadata": csvRecord.toString() // この処理は非常に雑です。
 +
}
 +
}
 +
geoJson.features.push(feature);
 +
}
 +
return(geoJson);
 +
}
 +
 
 +
</script>
 +
<body>
 +
<h3>CSVタイルデータの表示</h3>
 +
<div id="message">-</div>
 +
</body>
 +
</html>
 +
</pre>

2022年2月4日 (金) 09:33時点における版

目次

チュートリアル7 WebApp Layer ベクトルタイル

実際の動作は、こちらをクリック。


tiling1.html

<!DOCTYPE html>
<html>
<title>SVGMapLevel0.1-Rev14-Draft Tutorial2 Coastline & Air Port</title>
<!-- viewport 知表示領域を画面全体とする定義 -->
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<!-- SVGMapのコアAPIの読み込み -->
<script type="text/javascript" src="../js/SVGMapLv0.1_r17.js"></script>
<script type="text/javascript" src="../js/SVGMapLv0.1_LayerUI2_r4.js"></script>

<!-- SVGMap GISライブラリの読み込み-->
<script type="text/javascript" src="../js/jsts.min.js"></script>
<script type="text/javascript" src="../js/SVGMapLv0.1_GIS_r3.js"></script>

<!-- レイヤーリストUIのスタイルシート読み込み -->
<link href="../js/layerListStyle.css" rel="stylesheet" type="text/css">

<body bgcolor="#ffffff" style="overflow:hidden;" >
<!-- 地図SVGファイル(レイヤー)を複数含むコンテナファイル(Container.svg)の読み込み -->
 <div id="mapcanvas" data-src="Container.svg"></div>
 <div id="gui">
<!-- ズームアップボタン -->
  <img id="zoomupButton" style="left: 5px; top: 5px; position: absolute;" src="../img/zoomup.png" onclick="svgMap.zoomup()" width="20" height="20" />
<!-- ズームダウンボタン -->
  <img id="zoomdownButton" style="left: 5px; top: 25px; position: absolute;" src="../img/zoomdown.png" onclick="svgMap.zoomdown()" width="20" height="20" />
<!-- GPSボタン -->
  <img id="gpsButton" style="left: 5px; top: 45px; position: absolute;" src="../img/gps.png" onclick="svgMap.gps()" width="20" height="20" />
<!-- 画面右上に表示するタイトル -->
  <font color="blue" style="right: 5px; top: 5px; position: absolute;" >SVGMapLevel0.1 Rev14 Draft : Tutorial2 Coastline & Air Port</font>
<!-- 画面右下に表示する -->
  <font color="blue" style="right: 5px; bottom: 5px; position: absolute;" size="-2" >by SVGMap tech.</font>
<!-- 中央に表示される十字マーク -->
  <img id="centerSight" style="opacity:0.5" src="../img/Xcursor.png" width="15" height="15"/>
<!-- 画面左下に表示される十字マークの緯度・経度(タイトル) -->
  <font id="posCmt" size="-2" color="brown" style="left: 5px; bottom: 5px; position: absolute;">Lat,Lng:</font>
<!-- 画面左下に表示される十字マークの緯度・経度(実際の値の初期表示) -->
  <font id="centerPos" size="-2" color="brown" style="left: 50px; bottom: 5px; position: absolute;" >lat , lng</font>
<!-- レイヤーリストUIの表示 -->
  <div id="layerList" style="left :30px; top: 10px; width:300px;height:90%; position: absolute; "></div>
 </div>
</body>
</html>

Container.svg

  • チュートリアル6のhtmlと特に違いはありません。
    • GeoJsonデータはベクトルタイルデータのため、class属性でclickableを指定しています。
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="122.9800817, -45.398095, 21.97626, 21.0533039" >
 <globalCoordinateSystem srsName="http://purl.org/crs/84" transform="matrix(1,0,0,-1,0,0)" />

<!-- OpenStretMap背景地図を表示状態として読み込む -->
<animation xlink:href="../tutorial5/dynamicOSM_r11.svg" x="-3000" y="-3000" width="6000" height="6000" title="Japan Coastline" class="basemap" visibility="visible"/>

<!-- 日本の公共施設データのPoint CSVファイルのタイルデータを表示状態として読み込む -->
<animation xlink:href="simpleTiling.svg" x="-3000" y="-3000" width="6000" height="6000" title="Cultural Facility" class="POI clickable" visibility="visible"/>
</svg>

simpleTiling.svg

    • defs要素でアイコンを定義しています。
    • データの実体はここにはありません。webAppで動的に生成されます。
    • id="mapTiles"のグループ内に、タイルごとにサブグループが作られ、そこにアイコン(Point)が配置されます。
<?xml version="1.0" encoding="UTF-8"?>
<svg  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-42.8202042942663, -49.9999999999999, 513.842451531196, 600" xmlns:go="http://purl.org/svgmap/profile"  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" property="" data-controller="simpleTiling.html#exec=appearOnLayerLoad">
<defs>
<g id="p0">
  <circle cx="0" cy="0" r="5" fill="blue"/>
</g>
</defs>
<globalCoordinateSystem srsName="http://purl.org/crs/84" transform="matrix(100,0,0,-100,0,0)" />
<g id="mapTiles">
</g>
</svg>


simpleTiling.html

  • simpleTiling.svgに紐付けられ、そのDOMをコントロールできるwebApp
  • 表示領域に応じてタイル分割されたGeoJsonデータを動的に読み込みます。この点はチュートリアル5と類似しています。
    • 縮尺に応じたピラミッド構造は持っていないので、このチュートリアルのほうが単純です。
    • その代わり、小縮尺(縮小表示)では読み込むデータが大量になりすぎるので、読み込みを行わず、webAppのウィンド上に拡大を促すメッセージを出します。
  • addEventListener("zoomPanMap",zpmFunc): 伸縮スクロールが発生したときに、 zpmFunc()を呼び出す。
  • zpmFunc(): 表示領域に応じて読み込むべきタイルを選別して表示する
    • svgMap.getGeoViewBox(): 地理的な表示領域を取得
    • getTileList(geoViewBox):表示すべきタイルをリストアップする
    • delete tiles[tileKey]表示領域から外れたタイルのグループを消去
    • await loadCSV(): 既に読み込み済みのものを除き、表示すべきタイルデータ(CSV)を読み込み
    • drawTiles():読み込んだCSVデータを表示する
      • タイルを表示するためのグループを作成
      • csv2geojson: 読み込んだCSVからgeoJsonを生成する
      • svgMapGIStool.drawGeoJson(): geoJsonからSVGのDOMを生成
<!doctype html>
<html>
<head>
<title>Simple Tiling Tutorial</title>
<meta charset="utf-8"></meta>
</head>

<script>

addEventListener("load",init);
addEventListener("zoomPanMap",zpmFunc);

var latCol=10;
var lngCol=9;
var tilesTh=8; // 画面の中に入るタイルの枚数の閾値(縮小すると読み込むタイルが多くなりすぎ重くなるのを防ぐ)

function init(){
	zpmFunc();
}

function getTileList(geoViewBox){
	var tileNames={};
	for ( var ty = Math.floor(geoViewBox.y) ; ty<= Math.floor(geoViewBox.y+geoViewBox.height) ; ty++){
		for ( var tx = Math.floor(geoViewBox.x) ; tx <= Math.floor(geoViewBox.x+geoViewBox.width) ; tx++){
			var tile="tile_" + tx + "_" + ty;
			tileNames[tile]=true;
		}
	}
	return ( tileNames);
}

var tiles={}; // データ(CSVを配列化したもの)をタイルごとに格納する変数

async function zpmFunc(){
	var geoViewBox = svgMap.getGeoViewBox();
	var tileList=getTileList(geoViewBox);
	
	if (Object.keys(tileList).length < tilesTh ){
		for ( var tileKey in tiles ){ // 必要ないデータを消す
			if ( !tileList[tileKey]){
				delete tiles[tileKey];
			}
		}
		for ( var tileKey in tileList ){ // 不足しているデータを読み込む
			if ( !tiles[tileKey] ){
				tiles[tileKey]=await loadCSV(`tiles/${tileKey}.csv`); // テンプレートリテラル
			}
		}
		message.innerText="-";
		drawTiles(tileList);
	} else {
		message.innerText="Too many tiles, please zoom in.";
		removeAllTiles();
	}
}

function removeAllTiles(){
	tiles={};
	var groups = svgImage.getElementById("mapTiles").children;
	for ( var i = groups.length -1 ; i >= 0 ; i-- ){
		groups[i].remove(); 
	}
	svgMap.refreshScreen();
}

function drawTiles(tileList){
	// tileList:表示すべきタイルのキー(ID)の連想配列
	var tileGroup = svgImage.getElementById("mapTiles");
	var groups = tileGroup.children;
	for ( var i = groups.length -1 ; i >= 0 ; i-- ){
		var groupKey = groups[i].getAttribute("id");
		if ( !tileList[groupKey]){
			groups[i].remove(); // 表示する必要のないグループは消す
		} else {
			delete tileList[groupKey]; // すでに描画済みのタイルなのでtileListから消す
		}
	}
	// tileListは、新たに描画すべきタイルのリストとなった
	for ( var tileKey in tileList){
		var grp = svgImage.createElement("g");
		grp.setAttribute("id",tileKey);
		tileGroup.appendChild(grp);
		if ( tiles[tileKey] ){
			var geoJson = csv2geojson(tiles[tileKey], lngCol, latCol);
			svgMapGIStool.drawGeoJson(geoJson, layerID, "", 0, "", "p0", "poi", "", grp);
		}
		
	}
	svgMap.refreshScreen();
}

var schema;

async function loadCSV(url){
	var response = await fetch(url);
	if ( response.ok ){
		var txt = await response.text();
		txt=txt.split("\n");
		var csv=[];
		var schemaLine = true;
		for ( line of txt){
			line = line.trim();
			if ( schemaLine ){
				schema = line;
				svgImage.documentElement.setAttribute("property",schema);
			} else {
				if ( line !=""){
					line=line.split(",");
					csv.push(line);
				}
			}
			schemaLine = false;
		}
		return ( csv );
	} else {
		return ( null );
	}
}

function csv2geojson(csvArray, lngCol, latCol){
	var geoJson = {type: "FeatureCollection",  features: []}
	for ( var csvRecord of csvArray ){
		var lng = Number(csvRecord[lngCol]);
		var lat = Number(csvRecord[latCol]);
		var feature = { type: "Feature",
			geometry: {
				type: "Point",
				"coordinates": [lng, lat]
			},
			"properties": {
				"csvMetadata": csvRecord.toString() // この処理は非常に雑です。
			}
		}
		geoJson.features.push(feature);
	}
	return(geoJson);
}

</script>
<body>
<h3>CSVタイルデータの表示</h3>
<div id="message">-</div>
</body>
</html>
個人用ツール
名前空間

変種
操作
案内
ツール
Translate