D3.js 无法缩放或平移图块

D3.js can't zoom or pan tiles

我已经尝试了大约 10 天来使用 D3.js 创建显示矢量数据 (geojson) 的地图和我可以缩放和平移的栅格图块,但无法让它正常工作。我可以缩放和平移矢量数据,但不能缩放平移图块。

我注意到,当我调用 tile(transform) 时,尽管在转换中有我认为有意义的数字(例如 {"k": 1, " x”:-35,“y”:-37})。我在搞什么鬼?我假设问题出在下面的代码片段中的某个地方,尽管我还有完整的代码。

    const tile = d3.tile()
        .extent([[0, 0], [width, height]])

    let zoom = d3.zoom()
        .on('zoom', () => zoomed(d3.event.transform))
    svg.call(zoom)

    function zoomed(transform) {
        const tiles = tile(transform);

        lines.attr('transform', transform.toString())

        images = images.data(tiles, d => d)
            .join('image')
            .attr('xlink:href', d => 'https://tiles.wmflabs.org/bw-mapnik/' + d[2] + '/' + d[0] + '/' + d[1] + '.png')
            .attr('x', ([x]) => (x + tiles.translate[0]) * tiles.scale)
            .attr('y', ([, y]) => (y + tiles.translate[1]) * tiles.scale)
            .attr('width', tiles.scale)
            .attr('height', tiles.scale);
    }

下面是数据和完整的脚本。

{
"type": "FeatureCollection",
"name": "lines",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 3}, "geometry": { "type": "LineString", "coordinates": [ [ -74.201304101157845, 40.033790926216739 ], [ -74.201226425025339, 40.033761910802717 ], [ -74.201164135201353, 40.033738641825124 ] ] } },
{ "type": "Feature", "properties": { "id": 4}, "geometry": { "type": "LineString", "coordinates": [ [ -74.200521185229846, 40.034804885753857 ], [ -74.200535458528648, 40.034780636493231 ], [ -74.200698022608137, 40.034504451003734 ], [ -74.200932444446437, 40.034106179618831 ], [ -74.201017665586349, 40.033961391736824 ] ] } },
{ "type": "Feature", "properties": { "id": 5}, "geometry": { "type": "LineString", "coordinates": [ [ -74.243246789888346, 40.038535382572938 ], [ -74.243221882547942, 40.038496558418132 ], [ -74.243182498790546, 40.038435169141529 ], [ -74.243137176965064, 40.038364523771932 ], [ -74.243057495263045, 40.038240319569326 ], [ -74.242984178076739, 40.038126035633333 ], [ -74.242983803896664, 40.038125452375041 ], [ -74.242970932683164, 40.03810547276553 ], [ -74.242927580863451, 40.038038178902433 ] ] } }
]
}
    let width = 900,
        height = 500,
        initialScale = 1 << 17,
        initialCenter = [-74.20465,39.98783]

    let svg = d3.select('body')
        .append('svg')
        .attr('height', height)
        .attr('width', width)

    let map = svg.append('g')
    let images = map.append('g')
        .attr('pointer-events', 'none')
        .selectAll('image');

    let glines = map.append('g')
    let lines = glines.append('g')

    let projection = d3.geoMercator()
        .scale(initialScale)
        .center(initialCenter)
        .translate([width / 2, height / 2])

    let path = d3.geoPath(projection)

    const tile = d3.tile()
        .extent([[0, 0], [width, height]])

    let zoom = d3.zoom()
        .on('zoom', () => zoomed(d3.event.transform))
    svg.call(zoom)

    function zoomed(transform) {
        const tiles = tile(transform);

        lines.attr('transform', transform.toString())

        images = images.data(tiles, d => d)
            .join('image')
            .attr('xlink:href', d => 'https://tiles.wmflabs.org/bw-mapnik/' + d[2] + '/' + d[0] + '/' + d[1] + '.png')
            .attr('x', ([x]) => (x + tiles.translate[0]) * tiles.scale)
            .attr('y', ([, y]) => (y + tiles.translate[1]) * tiles.scale)
            .attr('width', tiles.scale)
            .attr('height', tiles.scale);
    }

    function drawMap(data) {
        let tiles = tile
            .scale(projection.scale() * 2 * Math.PI)
            .translate(projection([0, 0]))();

        lines.selectAll('path')
            .data(data.features)
            .enter()
            .append('path')
            .attr('class', 'line')
            .attr('d', path)

        images = images.data(tiles, d => d)
            .enter()
            .append('image')
            .attr('xlink:href', d => 'https://tiles.wmflabs.org/bw-mapnik/' + d[2] + '/' + d[0] + '/' + d[1] + '.png')
            .attr('x', d => (d[0] + tiles.translate[0]) * tiles.scale)
            .attr('y', d => (d[1] + tiles.translate[1]) * tiles.scale)
            .attr('width', tiles.scale)
            .attr('height', tiles.scale);
    }

    d3.json('test.geojson').then(drawMap)

我找到了一种更简单的方法,可以使用 D3 + Leaflet 在底图上放置线条。请参阅 https://observablehq.com/@sfu-iat355/intro-to-leaflet-d3-interactivity。创造奇迹。