我正在使用Leaflet Leaflet-D3's hexbin。我想将地图与hexbin图层导出到图像。为了将地图导出到图像,到目前为止我一直在使用Leaflet-image。但是,由于hexbin overlay是一个SVG图层,当我使用相同的库导出map + hexbin时,图像上只显示地图。
如何将该hexbin图层导出到Leaflet-image生成的同一图像中?例如,我已经看到了将SVG导出到图像的工具,但是在我的情况下这不会完全有效,因为它只能解决hexbin而不是地图。
答案 0 :(得分: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 = '© <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>
&#13;
我的初始代码没有考虑缩放和平移。这是重写。它有点疯狂所以我只用chrome测试过。说实话,此时,我会使用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 = '© <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>
&#13;