2016-08-11 6 views
3

Leaflet-D3's hexbinのリーフレットを使用しています。私は地図にの六角層をイメージにエクスポートしたかったのです。マップを画像にエクスポートするには、これまでのところLeaflet-imageを使用しています。しかし、六角形のオーバーレイはSVGレイヤーなので、同じライブラリを使ってマップ+ hexbinをエクスポートすると、マップのみがイメージに表示されます。リーフレットマップをエクスポートしてSVGレイヤーをイメージに添付

リーフレット画像で作成された同じ画像にそのhexbinレイヤーをエクスポートするにはどうすればよいですか?たとえばSVGをイメージにエクスポートするツールを見たことがありますが、これは私の場合は完全には機能しません。

答えて

3

これは実際にはかなりクールです。 hereというコードを使用すると、実際に生成されたリーフレットイメージとSVGから作成されたイメージを組み合わせることができます。

コードは言葉よりも雄弁に話すので、ここで私は一緒に入れたサンプルがあります:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script> 
 
    <script type="text/javascript" src="https://rawgit.com/d3/d3-plugins/master/hexbin/hexbin.js"></script> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script> 
 
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css"> 
 
    <script type="text/javascript" src="https://rawgit.com/Asymmetrik/leaflet-d3/master/dist/leaflet-d3.js"></script> 
 
    <script src="https://rawgit.com/mapbox/leaflet-image/gh-pages/leaflet-image.js"></script> 
 
</head> 
 

 
<body> 
 

 
    <div id="map" style="width: 600px; height: 400px; border: 1px solid #ccc"></div> 
 
    <button onclick="generateImage()">Create Image</button> 
 
    <div id="images"></div> 
 

 
    <script> 
 
    var center = [39.4, -78]; 
 

 
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
 
     osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors', 
 
     osm = L.tileLayer(osmUrl, { 
 
     maxZoom: 18, 
 
     attribution: osmAttrib 
 
     }); 
 

 
    map = new L.Map('map', { 
 
     layers: [osm], 
 
     center: new L.LatLng(center[0], center[1]), 
 
     zoom: 7 
 
    }); 
 

 
    var options = { 
 
     radius: 12, 
 
     opacity: 0.5, 
 
     duration: 500, 
 
     lng: function(d) { 
 
     return d[0]; 
 
     }, 
 
     lat: function(d) { 
 
     return d[1]; 
 
     }, 
 
     value: function(d) { 
 
     return d.length; 
 
     }, 
 
     valueFloor: 0, 
 
     valueCeil: undefined 
 
    }; 
 

 
    var hexLayer = L.hexbinLayer(options).addTo(map) 
 
    hexLayer.colorScale().range(['white', 'blue']); 
 

 
    var latFn = d3.random.normal(center[0], 1); 
 
    var longFn = d3.random.normal(center[1], 1); 
 
    
 
    var generateData = function() { 
 
     var data = []; 
 
     for (i = 0; i < 1000; i++) { 
 
     data.push([longFn(), latFn()]); 
 
     } 
 
     hexLayer.data(data); 
 
     
 
     d3.selectAll('.hexbin-hexagon') 
 
     .style({ 
 
      "stroke": '#000', 
 
      "stroke-width": '1px' 
 
     }); 
 
    }; 
 
    
 
    generateData(); 
 
    
 
    var getOverlay = function(){ 
 
     // Select the first svg element 
 
     var svg = d3.select('.leaflet-overlay-pane>svg'), 
 
      img = new Image(), 
 
      serializer = new XMLSerializer(), 
 
      svgStr = serializer.serializeToString(svg.node()); 
 
      
 
     img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr); 
 
     
 
     return { 
 
      img: img, 
 
      w: +svg.attr('width'), 
 
      h: +svg.attr('height') 
 
     } 
 
    }; 
 

 
    var generateImage = function() { 
 
     leafletImage(map, function(err, canvas) { 
 
     
 
     var d3O = getOverlay(); 
 
     canvas.getContext("2d").drawImage(d3O.img,0,0,d3O.w,d3O.h); 
 
     
 
     // now you have canvas 
 
     // example thing to do with that canvas: 
 
     var img = document.createElement('img'); 
 
     var dimensions = map.getSize(); 
 
     img.width = dimensions.x; 
 
     img.height = dimensions.y; 
 
     img.src = canvas.toDataURL(); 
 
     document.getElementById('images').innerHTML = ''; 
 
     document.getElementById('images').appendChild(img); 
 
     }); 
 
    }; 
 
    </script> 
 
</body> 
 

 
</html>

私の最初のコードでは、ズームやパン考慮されていませんでした。ここに書き直しがあります。それは少し狂っているので、私はクロムでのみテストしました。正直言って、この時点で、私はこのサーバ側をphantomJSでレンダリングし、それをJPEGにキャプチャしてブラウザに返します。

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script> 
 
    <script type="text/javascript" src="https://rawgit.com/d3/d3-plugins/master/hexbin/hexbin.js"></script> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script> 
 
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css"> 
 
    <script type="text/javascript" src="https://rawgit.com/Asymmetrik/leaflet-d3/master/dist/leaflet-d3.js"></script> 
 
    <script src="https://rawgit.com/mapbox/leaflet-image/gh-pages/leaflet-image.js"></script> 
 
</head> 
 

 
<body> 
 

 
    <div id="map" style="width: 600px; height: 400px; border: 1px solid #ccc"></div> 
 
    <button onclick="generateImage()">Create Image</button> 
 
    <div id="images"></div> 
 

 
    <script> 
 
    var center = [39.4, -78], 
 
     width = 600, 
 
     height = 400; 
 

 
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 
 
     osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors', 
 
     osm = L.tileLayer(osmUrl, { 
 
     maxZoom: 18, 
 
     attribution: osmAttrib 
 
     }); 
 

 
    map = new L.Map('map', { 
 
     layers: [osm], 
 
     center: new L.LatLng(center[0], center[1]), 
 
     zoom: 7 
 
    }); 
 

 
    var options = { 
 
     radius: 12, 
 
     opacity: 0.5, 
 
     duration: 500, 
 
     lng: function(d) { 
 
     return d[0]; 
 
     }, 
 
     lat: function(d) { 
 
     return d[1]; 
 
     }, 
 
     value: function(d) { 
 
     return d.length; 
 
     }, 
 
     valueFloor: 0, 
 
     valueCeil: undefined 
 
    }; 
 

 
    var hexLayer = L.hexbinLayer(options).addTo(map) 
 
    hexLayer.colorScale().range(['white', 'blue']); 
 

 
    var latFn = d3.random.normal(center[0], 1); 
 
    var longFn = d3.random.normal(center[1], 1); 
 
    
 
    var generateData = function() { 
 
     var data = []; 
 
     for (i = 0; i < 1000; i++) { 
 
     data.push([longFn(), latFn()]); 
 
     } 
 
     hexLayer.data(data); 
 
    }; 
 
    
 
    generateData(); 
 

 
    var getOverlay = function(){ 
 
     // Select the first svg element 
 
     var svg = d3.select('.leaflet-overlay-pane>svg'), 
 
      img = new Image(), 
 
      serializer = new XMLSerializer(); 
 
      
 
     svg.select("g").attr("transform", null); 
 
     svg.style("margin-top", null); 
 
     svg.style("margin-left", null); 
 
     svg.attr("height", null); 
 
     svg.attr("width", null); 
 
     var svgStr = serializer.serializeToString(svg.node()); 
 

 
     img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr); 
 
     
 
     return img; 
 
    }; 
 

 
    var generateImage = function() { 
 
     leafletImage(map, function(err, canvas) { 
 
     
 
     var t = d3.select('.leaflet-map-pane').style('transform').split(", "), 
 
      img = getOverlay(), 
 
      x = parseInt(t[4]), 
 
      y = parseInt(t[5]); 
 

 
     canvas.getContext("2d").drawImage(img, 
 
      x, 
 
      y, 
 
      width, 
 
      height 
 
     ); 
 
     
 
     // now you have canvas 
 
     // example thing to do with that canvas: 
 
     var img = document.createElement('img'); 
 
     var dimensions = map.getSize(); 
 
     img.width = dimensions.x; 
 
     img.height = dimensions.y; 
 
     img.src = canvas.toDataURL(); 
 
     document.getElementById('images').innerHTML = ''; 
 
     document.getElementById('images').appendChild(img); 
 
     }); 
 
    }; 
 
    </script> 
 
</body> 
 

 
</html>

+0

あなたのアイデアを愛して!しかし、それは完全には機能していません...非常に反応的ではないことに加えて(2回のクリックで1回しかキャプチャしないように見えます)、最終的な画像はキャプチャされたマップ+ [このスクリーンショット(ボルチモアを中心に)](https://snag.gy/Q7hLOE.jpg)をご覧ください。 [他のスクリーンショット](https://snag.gy/fkyFMD.jpg)でもご覧になれますように、別の問題がありました。これはあなたの特定の例に関連していますか? – pavlag

+1

さて、私はこのソリューションの問題点を知っています。 SVGレイヤ全体がキャプチャされ、キャンバス上に置かれます。マップ**を移動しないと、これはうまく動作します**。マップを側面にペイントすると、SVG全体が「非センタリング」マップの上に貼り付けられ、結果としてあなたに示したような画像が表示されます。だから、SVGレイヤーをマップのようにパンする必要があります。どうやって?イデオニアはありません... – pavlag

+0

@pavlag、解決する必要があります。私は最後の数日間旅行しています。今週私が帰ってきてくれますか? – Mark

関連する問題