d3.jsを使用したインタラクティブなSVGマップ

こんにちは、habrozhitel! 今日は、このJavaScriptライブラリーの一般的な可能性についてd3js.orgを使用してインタラクティブなSVGマップを作成する方法を説明します。また、Webの地理情報を保存する方法と場所を少し理解する必要があります。 最後に、次のものを取得します。



カートグラム

カットの下でこの魅力的な旅を始めることができます。



地図作成業務。



原則として、このセクションは、興味がなければ、セクションの最後にある目的のファイルへのリンクをスキップできます。 誰も気にせず、さらに理解します。 実際にマップとは、これは座標を参照した特定のオブジェクトのジオメトリに関する情報です。 GISシステムは通常、これらの目的でシェープファイルを使用します。 ロシアの地図を描画します。検索すると、おそらく私と同じ場所、つまりGIS-Labに移動します。 Albers-Siberiaプロジェクションを選択しました。 ダウンロード。 まず、シェープファイルをWGS 84標準(別名EPSG:4326)に変換する必要があります。 これを行うには、 Albers_Siberia.prj



などの投影ファイルを次の内容で作成します

 +proj=aea +lat_1=52 +lat_2=64 +lat_0=0 +lon_0=105 +x_0=18500000 +y_0=0 +ellps=krass +units=m +towgs84=28,-130,-95,0,0,0,0 +no_defs
      
      





次に、 GDALまたはそのOGRライブラリの1つを使用して、変換を実行します。 これらのニーズに対応するために、 Quantum GISをダウンロードしました。このGISには 、必要なものすべてがすでに含まれています。 インストール後、いくつかのショートカットが表示され、それらの中からOSGeo4W



探してクリックし、ファイルがあるディレクトリに移動して、次の形式のコマンドを入力します。

  ogr2ogr -f 'ESRI Shapefile' -s_srs Albers_Siberia.prj -t_srs EPSG:4326 input-fixed.shp input.shp
      
      





したがって、必要なシェープファイルを取得しましたが、必要に応じてWebにはまったく適していないので、データに基づいてGeoJSONファイルを生成します。 次に、GeoJSONからTopoJSONを生成します 。これは、 カートグラムに必要なものです。 これらは物事ですが、動揺しないでください。GeoJSONは便利な物でもあり、役に立つかもしれません。 それで、コンソールに戻り、次のように書きます。

  ogr2ogr -f GeoJSON output.json input.shp
      
      





GeoJSONファイルを取得して開き、GIS-Labからの驚きを確認します。

GIS-Lab Encryption
一般的に、この機能は元々シェープファイルに存在していましたが、この「楽しい」驚きはこの段階でのみ気づきました。 特徴は、地域のすべての名前が祖国の敵から暗号化され、クラッカーによって表示されることです。 しかし、私たちの男は暗号化された本を探す場所を知っています。 しかし、そこにありました。 単一のキリル文字エンコードが出てきませんでした(DOS-866には意味のある名前がありましたが、文字の一部が異なる四角に表示されていました)、私は思慮深くなり、インターネットで真実を探しましたこのカードのkrakozyabrについては何もありませんでした(そして2010年のカードは理解できます)ここで私は完全に必死で、再びEditPadを開きました(私の意見では、ほとんどのエンコーディングが提示され、実際に作業するのに非常に便利です)テキストとレギュラー)そして、すべてのエンコーディングを連続してソートし始めました。 鉱石MIKエンコード:(!?)ブルガリアは、私は、地域のすなわち名前を望んでいたほとんど何ました。 確かに、名前のすべての文字はDos記号separatedで区切られていました。まあ、単純なレギュラーシーズンでこの問題は非常に迅速に解決されました。 なぜ問題なのか、それは暗号であり、友人か誰かのテストに合格した=)。 ちなみに、このファイルには、GIS-Labで真実がすぐに言及されているというもう1つの特徴があります。つまり、チェスレ共和国とイングーシ共和国の地図には国境がありません。それだけです)。 ええ、はい、原則として、それは恐ろしいことではありません(もちろん誰にでも)が、不快な沈殿物が残りました。


次に、TopoJSONの生成に移りましょう。これにより、ファイルサイズを削減できます。 一般に、TopoJSONはトポロジに関するGeoJSONの最適化であり、冗長な情報を削除します。たとえば、近隣地域からの共通の境界の重複を削除します。 ただし、ジオメトリを単純化することで、ファイルサイズをさらに削減できます。 それでは始めましょう! Node.jsコマンドラインを起動し( TopoJSONを実装するために必要です)、次のように記述します。

  topojson -o output_topo.json -p -s 1e-7 -- name=input_geo.json
      
      





ここで、 -p



パラメーターはfeature properties



を保持し、 -s 1e-7



はジオメトリを単純化します1e-7



ステラジアンのしきい値で、ジオメトリが小さいほど正確です1e-3



は世界地図に対するスイス、 1e-9



サッカー場です。 なぜ必要なのか-マップでズーム機能を作成したい場合。 区切り記号--



、出力ファイルと入力ファイルの単なる区切り記号(K.O.)であり、 russia



プレフィックスはオブジェクトの名前を設定します。指定しない場合、入力ファイルの名前が名前として使用されますが、これは必ずしも便利ではありません(かさばることがあります)。 結果のファイルでは、地域の名前をISO 3166-2:RUに準拠したコードに置き換えました。 それだけです このファイルはGitHubで取得できます。



カートグラムを描く



地図を描くのか、それとも何を描くのか?! これで、d3.jsを使用してマップを描画するために必要なすべてが揃いました。 次のテンプレートをコピーして開始します。



 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Accidents on the Road - Choropleth</title> <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> <script type="text/javascript" src="http://d3js.org/queue.v1.min.js"></script> <script type="text/javascript" src="http://d3js.org/topojson.v0.min.js"></script> <!-- <script type="text/javascript" src="http://d3js.org/topojson.v1.min.js"></script> --> </head> <style> your awesome CSS </style> <body> <h1>Cool Header</h1> <script type="text/javascript"> Your awesome d3.js code </script> </body> </html>
      
      





最初に、SVGマップの寸法を設定します。



  var width = 960, height = 500;
      
      





カートグラムのカラードメイン、凡例のドメイン、凡例の署名を設定します。



  var color_domain = [50, 150, 350, 750, 1500] var ext_color_domain = [0, 50, 150, 350, 750, 1500] var legend_labels = ["< 50", "50+", "150+", "350+", "750+", "> 1500"] var color = d3.scale.threshold() .domain(color_domain) .range(["#adfcad", "#ffcb40", "#ffba00", "#ff7d73", "#ff4e40", "#ff1300"]);
      
      





ドキュメントに要素とツールチップクラスを追加します。



  var div = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0);
      
      





サイズ属性を持つSVGを追加します。



  var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height);
      
      





投影パラメーターを設定します(記事の冒頭のAlbers_Siberia.prjを参照してください)。



  var projection = d3.geo.albers() .rotate([-105, 0]) .center([-10, 65]) .parallels([52, 64]) .scale(700) .translate([width / 2, height / 2]); var path = d3.geo.path().projection(projection);
      
      





データを読み取ります。



  queue() .defer(d3.json, "/d/5685937/russia_1e-7sr.json") .defer(d3.csv, "Accidents.csv") .await(ready);
      
      





描画を開始します。 カップルの : -



:



オブジェクトを作成します。



  function ready(error, map, data) { var rateById = {}; var nameById = {}; data.forEach(function(d) { rateById[d.RegionCode] = +d.Deaths; nameById[d.RegionCode] = d.RegionName; });
      
      





カートグラムの描画と着色。



  svg.append("g") .attr("class", "region") .selectAll("path") .data(topojson.object(map, map.objects.russia).geometries) //.data(topojson.feature(map, map.objects.russia).features) <-- in case topojson.v1.js .enter().append("path") .attr("d", path) .style("fill", function(d) { return color(rateById[d.properties.region]); }) .style("opacity", 0.8)
      
      





イベントを処理します:領域の輝度を変更して(強調表示のため)、領域の名前と正確な数値をツールチップに表示します。



  .on("mouseover", function(d) { d3.select(this).transition().duration(300).style("opacity", 1); div.transition().duration(300) .style("opacity", 1) div.text(nameById[d.properties.region] + " : " + rateById[d.properties.region]) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY -30) + "px"); }) .on("mouseout", function() { d3.select(this) .transition().duration(300) .style("opacity", 0.8); div.transition().duration(300) .style("opacity", 0); })
      
      





今、私はこの非常にマップに何かを追加する方法を学びたいと思います、私は実際に都市自体とその座標(緯度と経度の小数度)が必要であるため、ロシアの百万以上の都市を追加することにしました、残念ながらこのgpsvisualizer.com/彼がロシア語を理解できるようにジオコーダー 、私は(誰も知ることができますか?)できませんでしたが、特にリストが小さいので、Yandex.Map APIに行きたくありませんでした。 彼ら自身がそのような魔術師を行えばいいのですが、まあ、私は気が散りました。 その結果、次のタイプのリストが得られました。



 City lat lon  55.7522200 37.6155600 - 59.8944400 30.2641700
      
      





まあ、実際には、それらをグループに追加します: -







  d3.tsv("cities.tsv", function(error, data) { var city = svg.selectAll("g.city") .data(data) .enter() .append("g") .attr("class", "city") .attr("transform", function(d) { return "translate(" + projection([d.lon, d.lat]) + ")"; }); city.append("circle") .attr("r", 3) .style("fill", "lime") .style("opacity", 0.75); city.append("text") .attr("x", 5) .text(function(d) { return d.City; }); }); };
      
      





ここでは、ポイントの代わりに、たとえばパイ/リング図を追加して、カートグラムの情報負荷を増やすことができます。 一般的に、多くの可能性があり、すべてがUI / UXの観点からのタスク、想像力、および便宜によって制限されます。



最後に、カートグラムに凡例を追加します。



  var legend = svg.selectAll("g.legend") .data(ext_color_domain) .enter().append("g") .attr("class", "legend"); var ls_w = 20, ls_h = 20; legend.append("rect") .attr("x", 20) .attr("y", function(d, i){ return height - (i*ls_h) - 2*ls_h;}) .attr("width", ls_w) .attr("height", ls_h) .style("fill", function(d, i) { return color(d); }) .style("opacity", 0.8); legend.append("text") .attr("x", 50) .attr("y", function(d, i){ return height - (i*ls_h) - ls_h - 4;}) .text(function(d, i){ return legend_labels[i]; });
      
      





それは基本的にそれです、私は簡単な例で要点を示しようとしました、私は成功したことを望みます。 コードは確かに完璧ではありません(完璧ではありません)が、目標は理解しやすくすることであり、非常に普遍的/効率的ではありません。 ソースはGitHubで見つけることができ、 bl.ocks.orgサービスで結果を感じることができます。 はい、ここではCSSを考慮しませんでしたが、すべては簡単です。



結果。 次は?



さて、ここでは単純なカートグラムを作成しました。接近する可能性はなく、複雑なアニメーションやその他の機能はありませんが、ここに追加したい場合は難しくありません。 一般に、このライブラリには、グラフ、チャート、カートグラム、ツリー、グラフ、チャート、ヒートマップなど、あらゆるものを視覚化するための最も広い可能性があります... これがDataVizハーベスターです。必要なものはすべてd3js.org Webサイトから入手できます。 Mike Bostockはプロジェクトを積極的に開発しており、ほぼ毎日新しいサンプルをアップロードしています(1つマイナス、ほとんどコメントなし)。Mike自身も含め、 stackoverflowに迅速に対応するものがたくさんあります。 それでは、基本的に丘の背後にある主要な視覚化ツールであるこのライブラリは、私たちの注意を不当に奪われています。 さて、私は、もしそれがhabro-communityにとって興味深いのであれば、定期的に興味深い例を分析します。 実際、すべてのもの、コメント、質問、提案を歓迎します。



PS最も重要なことを忘れてしまいました。特にチュコトカから来ていない場合は、道路に注意してください。あらゆる種類のフリークがあり、レジストラからの多くのビデオがこれを確認しています! 一般に、悲しいことに、年間約2万8千人が死亡し、恐怖は単純です(データは交通警察のWebサイトから取得されました)。



All Articles