我正在尝试使用d3-geo-voronoi使用d3-tile显示矢量图块数据。我最初的尝试是在显示数据时将填充设置为“ none”,但这种尝试非常有效!Voronoi tile map without color fill
但是,当我尝试填充多边形时,某些拼贴变形了。Voronoi tile map with color fill
我无法弄清楚为什么会这样。我检查了dom中的svg,一切看起来正确。没有多边形的svg是正确的,只是没有正确渲染它们,可能是被掩盖了。下面是我使用的代码:
const d3 = require('d3');
const d3tile = require('d3-tile');
const d3geovoronoi = require('d3-geo-voronoi');
const vt2geojson = require('@mapbox/vt2geojson');
const pi = Math.PI,
tau = 2 * pi;
const width = Math.max(960, window.innerWidth),
height = Math.max(500, window.innerHeight);
const map = d3.select("body").append("div")
.attr("class", "map")
.style("width", width + "px")
.style("height", height + "px")
.on("mousemove", mousemoved);
let projection = d3.geoMercator()
.scale(1 / tau)
.translate([0, 0]);
let center = projection([-76.3, 38.794745]);
const tile = d3tile.tile()
.size([width, height]);
const zoom = d3.zoom()
.scaleExtent([1 << 15, 1 << 24])
.on("zoom", zoomed);
const svg = map.append("g")
.attr("pointer-events", "none")
.attr("class", "svg");
const info = map.append("g")
.attr("class", "info");
const ramp = d3.scaleLinear().domain([0.05,0.07]).interpolate(d3.interpolateHcl).range(['#34d8eb','#3a34eb']).unknown("#5c5752")
map.call(zoom)
.call(zoom.transform, d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(1 << 21)
.translate(-center[0], -center[1]));
function zoomed() {
let transform = d3.event.transform;
let tiles = tile(transform);
let image = svg
.style("transform", stringify(tiles.scale, tiles.translate))
.selectAll(".tile")
.data(tiles, function(d) { return d; })
.enter().append("svg")
.attr("class", "tile")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-width", "0.5")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.style("left", function(d) { return d[0] * 256 + "px"; })
.style("top", function(d) { return d[1] * 256 + "px"; })
.each(function(d) { this._xhr = render(d, this); });
projection
.scale(transform.k / tau)
.translate([transform.x, transform.y]);
}
function render(d, xnode) {
let k = Math.pow(2, d[2]) * 256;
vt2geojson({
uri: 'http://localhost:7800/public.r3sim_fort_temp/'+d[2]+'/'+d[0]+'/'+d[1]+'.pbf?properties=node,zeta,mask,bathymetry'
}, function (err, json) {
if (err) throw err;
d3.select(xnode)
.selectAll("path")
.data(d3geovoronoi.geoVoronoi().polygons(json).features)
.enter().append("path")
//.attr('fill', 'none')
.attr("fill", function(d) {return ramp(d.properties.site.properties.zeta)})
.attr("stroke", "#fff")
.attr("stroke-width", "0.5")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", d3.geoPath()
.projection(d3.geoMercator()
.scale(k / tau)
.translate([k / 2 - d[0] * 256, k / 2 - d[1] * 256])
.precision(0)));
})
}
function stringify(scale, translate) {
const k = scale / 256, r = scale % 1 ? Number : Math.round;
return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")";
}
function mousemoved() {
info.text(formatLocation(projection.invert(d3.mouse(this)), d3.zoomTransform(this).k));
}
function formatLocation(p, k) {
const format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
return (p[1] < 0 ? format(-p[1]) + "°S" : format(p[1]) + "°N") + " "
+ (p[0] < 0 ? format(-p[0]) + "°W" : format(p[0]) + "°E");
}
<!doctype html>
<head>
<meta charset="utf-8">
<title>D3 V5 Vector Tile Example</title>
<style>
body {
margin: 0;
}
.map {
background: #5c5752;
position: relative;
overflow: hidden;
}
.svg {
position: absolute;
will-change: transform;
}
.tile {
position: absolute;
width: 256px;
height: 256px;
}
.info {
position: absolute;
bottom: 10px;
left: 10px;
}
</style>
</head>
<body>
<script src="bundle.js"></script>
</body>
在此示例中,我用不同的颜色值填充了多边形。但是,如果使用单一颜色值,则会发生完全相同的失真。如果我重新加载所有数据,这些失真也总是在同一位置。
我深入研究了数据,找到了错误的svg路径,然后找到了与之相关的数据。看起来d3.geo.voronoi正在生成一些错误的坐标,但输入数据看起来还不错。以下是节点1192的两个打印输出。第一个是输入的geojson数据,显示了坐标,第二个是voronoi几何。 voronoi几何包含东半球(103.86 ...)中的经度值,该值超出了数据范围。我仍在尝试确定为什么会产生这些不良值。同样,输入坐标看起来正确,但是可能是其他数据进入了voronoi计算?
1192
{…}
geometry: {…}
coordinates: (2) […]
0: -76.12801194190979
1: 38.78622954627738
length: 2
<prototype>: Array []
type: "Point"
<prototype>: Object { … }
properties: Object { node: 180407, zeta: "NaN", mask: "True", … }
type: "Feature"
<prototype>: Object { … }
1192 (11) […]
0: Array [ 103.86695733932268, -44.964779133003304 ]
1: Array [ -76.13308210176842, 38.75793814039401 ]
2: Array [ -76.13020999558496, 38.782688154120585 ]
3: Array [ -76.12890669699081, 38.78647064351637 ]
4: Array [ -76.12807302385534, 38.786723650244355 ]
5: Array [ -76.12754554182737, 38.78651000385868 ]
6: Array [ -76.12640847594942, 38.78408839960177 ]
7: Array [ -76.11435851540921, 38.636536130021334 ]
8: Array [ 103.858096036925, -39.00570100251519 ]
9: Array [ 103.860092112702, -39.367933188411186 ]
10: Array [ 103.86695733932268, -44.964779133003304 ]
length: 11
<prototype>: []