【问题标题】:D3-Tile Not All Tiles LoadD3-Tile 并非所有瓷砖都加载
【发布时间】:2018-03-07 21:01:04
【问题描述】:

我正在尝试使用 D3 v4 和 d3-tile v0.0.4 重现 this example(如 this question 中所述,需要进行一些小调整)。为简单起见,我删除了光栅矢量并将窗口大小设置为 960x500。

在多个缩放和平移位置,左上角的图块不会加载。关于为什么的任何想法?我需要选择不同的窗户尺寸吗?我建议全屏展开代码 sn -p 来查看问题。

当我运行基本相同的示例但使用 d3-tile v0.0 时,问题就消失了,因此更新中肯定发生了一些变化。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    body {
        margin: 0;
    }

    path {
        fill: none;
        stroke: red;
        stroke-linejoin: round;
        stroke-width: 1.5px;
    }
</style>
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/d3-tile@0.0.4/build/d3-tile.js"></script>
<script>
    var pi = Math.PI,
        tau = 2 * pi;

    var width = 960;
        height = 500;

    // Initialize the projection to fit the world in a 1×1 square centered at the origin.
    var projection = d3.geoMercator()
        .scale(1 / tau)
        .translate([0, 0]);

    var path = d3.geoPath()
        .projection(projection);

    var tile = d3.tile()
        .size([width, height]);

    var zoom = d3.zoom()
        .scaleExtent([1 << 11, 1 << 14])
        .on("zoom", zoomed);

    var svg = d3.select("svg")
        .attr("width", width)
        .attr("height", height);

    var raster = svg.append("g");

    // Compute the projected initial center.
    var center = projection([-98.5, 39.5]);

    // Apply a zoom transform equivalent to projection.{scale,translate,center}.
    svg
        .call(zoom)
        .call(zoom.transform, d3.zoomIdentity
            .translate(width / 2, height / 2)
            .scale(1 << 12)
            .translate(-center[0], -center[1]));

    function zoomed() {
        var transform = d3.event.transform;

        var tiles = tile
            .scale(transform.k)
            .translate([transform.x, transform.y])
            ();

        projection
            .scale(transform.k / tau)
            .translate([transform.x, transform.y]);

        var image = raster
            .attr("transform", stringify(tiles.scale, tiles.translate))
            .selectAll("image")
            .data(tiles, function(d) {
                return d;
            });

        image.exit().remove();

        image.enter().append("image")
            .attr('xlink:href', function(d) {
                return 'http://' + 'abc' [d.y % 3] + '.tile.openstreetmap.org/' +
                    d.z + '/' + d.x + '/' + d.y + '.png';
            })
            .attr('x', function(d) {
                return d.x * 256;
            })
            .attr('y', function(d) {
                return d.y * 256;
            })
            .attr("width", 256)
            .attr("height", 256);
    }

    function stringify(scale, translate) {
        var k = scale / 256,
            r = scale % 1 ? Number : Math.round;
        return "translate(" + r(translate[0] * scale) + "," + r(translate[1] * scale) + ") scale(" + k + ")";
    }
</script>

【问题讨论】:

    标签: javascript d3.js tile


    【解决方案1】:

    所有的瓷砖都是从我能看到的地方画出来的。如果您查看 DOM,有适当数量的图块,只是第一个图块看起来好像它从未正确退出(应该如此);然而,它被分配了新的数据。但是,由于您不使用更新选择,它永远不会更新第一次绘制的剩余位置。如果您向西滚动,这会导致图像重叠,或者如果向东滚动,则会导致屏幕外的隐藏图像。

    一种解决方案是使用完整的退出/进入/合并/更新周期,但这会留下令人不满意的结果,即不知道为什么会首先发生意外行为:

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
        body {
            margin: 0;
        }
    
        path {
            fill: none;
            stroke: red;
            stroke-linejoin: round;
            stroke-width: 1.5px;
        }
    </style>
    <svg></svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://unpkg.com/d3-tile@0.0.4/build/d3-tile.js"></script>
    <script>
        var pi = Math.PI,
            tau = 2 * pi;
    
        var width = 960;
            height = 500;
    
        // Initialize the projection to fit the world in a 1×1 square centered at the origin.
        var projection = d3.geoMercator()
            .scale(1 / tau)
            .translate([0, 0]);
    
        var path = d3.geoPath()
            .projection(projection);
    
        var tile = d3.tile()
            .size([width, height]);
    
        var zoom = d3.zoom()
            .scaleExtent([1 << 11, 1 << 14])
            .on("zoom", zoomed);
    
        var svg = d3.select("svg")
            .attr("width", width)
            .attr("height", height);
    
        var raster = svg.append("g");
    
        // Compute the projected initial center.
        var center = projection([-98.5, 39.5]);
    
        // Apply a zoom transform equivalent to projection.{scale,translate,center}.
        svg
            .call(zoom)
            .call(zoom.transform, d3.zoomIdentity
                .translate(width / 2, height / 2)
                .scale(1 << 12)
                .translate(-center[0], -center[1]));
    
        function zoomed() {
            var transform = d3.event.transform;
    
            var tiles = tile
                .scale(transform.k)
                .translate([transform.x, transform.y])
                ();
    
            projection
                .scale(transform.k / tau)
                .translate([transform.x, transform.y]);
    
            var image = raster
                .attr("transform", stringify(tiles.scale, tiles.translate))
                .selectAll("image")
                .data(tiles, function(d) {
                    return d;
                });
    
            image.exit().remove();
            // enter:
            var entered = image.enter().append("image");
            // update:
            image = entered.merge(image)
                .attr('xlink:href', function(d) {
                    return 'http://' + 'abc' [d.y % 3] + '.tile.openstreetmap.org/' +
                        d.z + '/' + d.x + '/' + d.y + '.png';
                })
                .attr('x', function(d) {
                    return d.x * 256;
                })
                .attr('y', function(d) {
                    return d.y * 256;
                })
                .attr("width", 256)
                .attr("height", 256);
        }
    
        function stringify(scale, translate) {
            var k = scale / 256,
                r = scale % 1 ? Number : Math.round;
            return "translate(" + r(translate[0] * scale) + "," + r(translate[1] * scale) + ") scale(" + k + ")";
        }
    </script>

    【讨论】:

    • 看起来可行,但同意目前尚不清楚为什么会发生这种行为。可能值得向 GitHub 提交问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多