スポンサーリンク

Leaflef.jsとD3.jsでマップデータを可視化してみた

D3.js JavaScript データビジュアライゼーション 地理データ

Leaflet.jsというWebマップ表示ライブラリを知りましたので、使ってみました。

Leaflet.js

Leaflet.js : http://leafletjs.com/

結構前からあったそうな。

OpenStreetMapは知っていたけども、敷居が高そうと思っていましたが、たったこれだけのソースで表示できてしまった...。

function _map(){
  this.targetDivId = "map";
  this.leafletMap;
  this.viewLocation = {"lon": 139.691706, "lat": 35.689488};
  this.mapLink = 'OpenStreetMap';
}
// _map draw
_map.prototype.draw = function(){
  this.leafletMap = L.map(this.targetDivId).setView([this.viewLocation.lat, this.viewLocation.lon], 4);
  L.tileLayer(
    "http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png", {
      attribution: "© " + this.mapLink + " Contributors",
      maxZoom: 18,
    }
  ).addTo(this.leafletMap);
  this.leafletMap._initPathRoot();
}
// init
function init(){
  var map = new _map();
  map.draw();
}

カスタマイズ性が低いとのことだけども、地図自体はカスタマイズする機会も少ないだろうし、基本的な可視化機能として、マーカーを置いたり、地形に色を塗ったりできるようです。

使いこなしていけば、いろんなことが出来るかもしれません。

D3.jsとの連携

ちなみにD3.jsとの連携も出来るようです。

実際に簡単にやってみたところ、このような感じになりました。

var map, svg, g;
function init(){
  map = L.map("map").setView([39.702053, 141.15448379999998], 6);
  L.tileLayer(
    "http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png", {
    attribution: '© OpenStreetMap Contributiors',
    maxZoom: 18,
  }).addTo(map);
  map._initPathRoot();
  svg = d3.select("#map").select("svg");
  g = svg.append("g");
  d3.json("data/japan.geojson", function(json){
    drawpolygon(json);
    d3.json("data/points.geojson", function(json){
      drawpoint(json);
    });
  });
}
function drawpolygon(json){
  var geojson = json.type == "Topology" ? topojson.feature(json, json.objects.ken) : json;
  var transform = d3.geo.transform({point: projectPoint});
  var path = d3.geo.path().projection(transform);
  featureElement = g.selectAll("path")
    .data(geojson.features)
    .enter()
    .append("path")
    .attr({
      "stroke": "#00AA11",
      "fill": "#AAFFAA",
      "fill-opacity": 0.4,
    });
  map.on("viewreset", update);
  update();
  function update (){
    featureElement.attr("d", path);
  }
  function projectPoint(x, y){
    var point = map.latLngToLayerPoint(new L.LatLng(y, x));
    this.stream.point(point.x, point.y);
  }
}
function drawpoint(json){
  json.features.forEach(function(d){
    d.LatLngObj = new L.LatLng(d.geometry.coordinates[1], d.geometry.coordinates[0]);
  });
  var circle = g.selectAll("circle")
    .data(json.features)
    .enter()
    .append("circle")
    .attr({
      "stroke": "black",
      "stroke-width": 1,
      "opacity": 0.7,
      "fill": "red",
      "r": 10,
    });
  map.on("viewreset", update);
  update();
  function update(){
    circle.attr("transform", function(d){
      return "translate(" + map.latLngToLayerPoint(d.LatLngObj).x + "," + map.latLngToLayerPoint(d.LatLngObj).y + ")";
    });
  }
}

いやいや十分でしょ!

あとは、D3.jsのスケール関数とかで色の濃淡や、ポイント円の大きさでデータを表示もできますし、ポイント間に線を引っ張ることもできますし。

2D地図のオーバーレイ可視化で良いのならば、かなり多彩な表現が可能なのでは...。

D3.jsでgeojsonやtopojsonを読み込んで地形を表示して頑張る必要はなかったらしい笑

まあ、デザイン性を追求するならば、自前で頑張るのも良いかもしれませんが、しかし、拡大・縮小で自動的に地名や境界線などの粒度も調整してくれる地図クライアントツールってところは大きいですねー。

うーん、これで色々と格好良く便利に可視化してみたいです。

コメント