チュートリアル14
提供: svg2wiki
目次 |
チュートリアル14 WebApp Layer geoJSON
動的にベクトルデータが生成・配信されているサービスをSVGMap.jsに結合します。ここではUSGS Hazards Programが配信している、世界の地震発生状況データ(GeoJSON版)を結合してみます。基本的にはチュートリアル6との違いはありません。
- 実際の動作は、こちらをクリック。
- ソースコードのディレクトリ
geojson1.html
- チュートリアル6と特に違いはありません。
Container.svg
- チュートリアル6と特に違いはありません。
geoJsonExample2.svg
- ドキュメントルート要素(svg要素)の、data-controller属性で、このレイヤーを操作するwebAppを指定しています。
data-controller="geoJsonExample1.html#exec=appearOnLayerLoad
exec=appearOnLayerLoad
は、レイヤが表示状態になるとwebAppのウィンドが出現する設定です。(詳しくはこちら)
- defs要素でマーカー(POIのアイコン)を定義しています
- マーカーの色はマグニチュードに応じて変化させるためここでは未定義にしてあります
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:go="http://purl.org/svgmap/profile" viewBox="12375.0 -4500.0 2250.0 2250.0" go:dataArea="12375.0 -4500.0 2250.0 2250.0" data-controller="geoJsonExample2.html#exec=appearOnLayerLoad" property="name,address,phone,url"> <defs> <g id="p0"> <circle cx="0" cy="0" r="10" stroke="none"/> </g> </defs> <globalCoordinateSystem srsName="http://purl.org/crs/84" transform="matrix(100.0,0.0,0.0,-100.0,0.0,0.0)" /> <g id="mapContents"></g> </svg>
geoJsonExample2.html
- geoJsonExample2.svgに紐付けられ、そのDOMをコントロールできるwebApp
- チュートリアル6#geoJsonExample1.htmlに対して以下が相違点
addEventListener("load", function(){..})
-
changeData()
UIの設定に基づき、地震データをリクエストして可視化する関数-
getUSGSURL()
USGSが配信する地震データを取得するためのGETリクエストを生成 -
loadAndDrawGeoJson()
buildSchema
- 解説書#drawGeoJson関数で可視化する際に、SVGMap.jsが持つメタデータ表示フレームワークに適応させるためのスキーマデータを構築している。
- drawGeoJson関数の末尾の引数(metaSchema)を生成
setMagColors
- 解説書#drawGeoJson関数の持つ、各フィーチャーのproperties値を使ってスタイルを設定可能な機能を使い、マグニチュード値をもとにpointフィーチャの色を指定
-
-
-
setInterval(function(){..}..)
指定した間隔で定期的にデータを陸セスとして表示を更新する関数(地震データはリアルタイムに更新されるため)
-
<!doctype html> <html> <head> <meta charset="utf-8"/> <title>SVGMapのwebAppレイヤーで、geoJsonを描画するサンプル</title> </head> <script> var usgsEarthquakeService="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"; var timeSpanKeys=["hour","day","week","month"]; // 配信データの期間設定の選択枝 var timeSpanDefault=2; // 過去1週間のデータの表示をデフォルトに var levelKeys=["significant","4.5","2.5","1.0","all"]; // マグニチュード別の配信データの選択枝 var levelDefault=2; // M2.5以上の地震の表示をデフォルトに var intervalMinutes=10; // 10分おきに更新する var metaSchema; // SVGMap.jsの標準で用意されているジオメトリ選択時のメタデータ表示UIの正規化されたスキーマを格納する addEventListener("load", function(){ buildDataSelect(); changeData(); setInterval(function(){ changeData(); messageDiv.innerText=new Date().toLocaleString() + " update"; } ,intervalMinutes * 60 * 1000); }); function changeData(){ var param1 = dataSelect1.selectedIndex; var param2 = dataSelect2.selectedIndex; var path = getUSGSURL(param1,param2); loadAndDrawGeoJson(path); } async function loadAndDrawGeoJson(dataPath){ var gjs = await loadJSON(dataPath); buildSchema(gjs.features); setMagColors(gjs.features); console.log("geoJson:",gjs); var parentElm = svgImage.getElementById("mapContents"); removeChildren(parentElm); svgMapGIStool.drawGeoJson(gjs, layerID, "orange", 2, "orange", "p0", "poi", "", parentElm, metaSchema); svgMap.refreshScreen(); } function buildDataSelect(){ var first=true; for ( var i = 0 ; i < timeSpanKeys.length; i++){ var timeSpanKey = timeSpanKeys[i]; var selectedOpt=""; if ( timeSpanDefault == i){ selectedOpt="selected"; } dataSelect1.insertAdjacentHTML('beforeend', `<option value="${timeSpanKey}" ${selectedOpt}>${timeSpanKey}</option>`); } for ( var i = 0 ; i < levelKeys.length ; i++){ var levelKey = levelKeys[i]; var selectedOpt=""; if ( levelDefault == i){ selectedOpt="selected"; } dataSelect2.insertAdjacentHTML('beforeend', `<option value="${levelKey}" ${selectedOpt}>${levelKey}</option>`); } } async function loadJSON(url){ var response = await fetch(url+"?time="+new Date().getTime()); // 常に最新のデータを得るには何かダミーのクエリパートを付けるBad Tips.. // https://stackoverflow.com/questions/37204296/cache-invalidation-using-the-query-string-bad-practice // https://stackoverflow.com/questions/9692665/cache-busting-via-params var json = await response.json(); return ( json ); } function removeChildren(element){ while (element.firstChild) element.removeChild(element.firstChild); } function getUSGSURL(timeSpan, level){ if (!timeSpanKeys[timeSpan]){return}; if (!levelKeys[level]){return}; var ans = `${usgsEarthquakeService}${levelKeys[level]}_${timeSpanKeys[timeSpan]}.geojson`; console.log("getUSGSURL:",ans); return (ans); } function buildSchema(features){ // geojsonのfeatureのproprerty名から正規化されたスキーマを生成 metaSchema={}; for ( var feature of features){ // 一応全データをトレース for ( var propName in feature.properties){ if (!metaSchema[propName]){ metaSchema[propName]=true; } } } metaSchema=Object.keys(metaSchema); svgImage.documentElement.setAttribute("property",metaSchema.join()); } function setMagColors(features){ // [[解説書#drawGeoJson]]のスタイリング仕様を使い、マグニチュードに応じた色を付ける for ( var feature of features){ var mag = feature.properties.mag; // マグニチュード3...7でクリッピング mag = Math.max(3,mag); mag = Math.min(7,mag); // 色相(hue)に変換し、そこからRGBカラーを生成 var hue = (7-mag)/(4)*240; var rgb = svgMapGIStool.hsv2rgb(hue,100,100); console.log(rgb); if ( rgb){ feature.properties["marker-color"]=`#${rgb.r.toString(16).padStart(2, '0')}${rgb.g.toString(16).padStart(2, '0')}${rgb.b.toString(16).padStart(2, '0')}`; } } console.log(features); } </script> <body> <h3>area layer</h3> <p><a href="https://earthquake.usgs.gov/earthquakes/feed/">USGS Earthquake Hazards Program Feed</a>の可視化</p> 期間<select id="dataSelect1" onchange="changeData()"></select><br> 規模<select id="dataSelect2" onchange="changeData()"></select> <div id="messageDiv"></div> </body> </html>