チュートリアル14
提供: svg2wiki
目次 |
チュートリアル14 WebApp Layer ベクトル地理情報サービスの結合
動的にベクトルデータが生成・配信されているサービスをSVGMap.jsに結合します。ここではUSGS Hazards Programが配信している、リアルタイム世界の地震発生状況データ(GeoJSON Real-time Feeds)(GeoJSON版)を結合してみます。基本的にはチュートリアル6との違いはありません。
- 実際の動作は、こちらをクリック。
- 使用ファイルのZIPアーカイブファイル
geojson1.html
- チュートリアル6と特に違いはありません。
Container.svg
- チュートリアル6と特に違いはありません。
geoJsonExample2.svg
- ドキュメントルート要素(svg要素)の、data-controller属性で、このレイヤーを操作するwebAppを指定しています。
data-controller="geoJsonExample2.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" 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.js
USGS Earthquake GeoJSON Real-time Feedsサービスについて
このサービスは全世界の地震発生状況を更新間隔1分リアルタイム配信しています。出力形式はGeoJson、出力データは時間間隔および地震規模でいくつか選択できるようになっています。リクエストにはクエリパートはなく、更新されたデータが常に同じURLで配信されます。
コード
- geoJsonExample2.svgに紐付けられ、そのDOMをコントロールできるwebApp
- チュートリアル6#geoJsonExample1.htmlに対して以下が相違点
addEventListener("load", function(){..})
-
changeData()
UIの設定に基づき、地震データをリクエストして可視化する関数-
getUSGSURL()
USGSが配信する地震データを取得するためのGETリクエストを生成- クロスオリジンアクセスを行うリクエストを作っています。USGS Earthquake GeoJSON Real-time Feedsは
access-control-allow-origin: *
レスポンスヘッダを持っているためアクセス可能です。
- クロスオリジンアクセスを行うリクエストを作っています。USGS Earthquake GeoJSON Real-time Feedsは
-
loadAndDrawGeoJson()
非同期でjsonデータを取得し描画する関数loadJSON()
ブラウザ側キャッシュを効かせないように、常に変化する適当なクエリパートをつけています(getTime()
より適切な方法がありますが、ここでは古典的なBad Tipsを用いています)buildSchema()
- svgMapGIStool.drawGeoJson関数で可視化する際に、SVGMap.jsが持つメタデータ表示フレームワークに適応させるためのスキーマデータを構築するとともに、SVGMapコンテンツのドキュメントルート要素に設定
- svgMapGIStool.drawGeoJson関数で渡す末尾の引数(metaSchema)を生成している
setMagColors()
- svgMapGIStool.drawGeoJson関数の持つ、各フィーチャーのproperties値を使ってスタイルを設定可能な機能を使い、マグニチュード値をもとにpointフィーチャの色を指定
svgMapGIStool.drawGeoJson()
buildSchema()
で生成したスキーマ(metaSchema
)を与え、SVGMap.jsのメタデータ表示フレームワークでメタデータがうまく表示できるようにしています
-
-
setInterval(function(){..}..)
指定した間隔で定期的に更新する関数(地震データはリアルタイムに更新されるため)
-
geoJsonExample2.html
<!doctype html> <html> <head> <meta charset="utf-8"/> <title>SVGMapのwebAppレイヤーで、geoJsonを描画するサンプル</title> </head> <script src="https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/svgMapLayerLib.js"></script> <script src="geoJsonExample2.js"></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>
geoJsonExample2.js
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]]のスタイリング仕様を使い、マグニチュードに応じた色を付ける features.sort(function(a,b){ //マグニチュード昇順でソート return(a.properties.mag - b.properties.mag); }); for ( var feature of features){ var cmag = feature.properties.mag; // マグニチュード3...7でクリッピング cmag = Math.max(3,cmag); cmag = Math.min(7,cmag); // 色相(hue)に変換し、そこからRGBカラーを生成 var hue = (7-cmag)/(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); }
appendix:クロスオリジンアクセス
クロスオリジンアクセス については(独立したページに移行しました)