Статический svg на базовой карте листовки. Проекция d3 js json - PullRequest
0 голосов
/ 07 сентября 2018

Я работаю над визуализацией миграции из города в город, и у меня возникла проблема ... Я хочу отобразить свою карту поверх базовой карты листовки. Проблема состоит в том, что карта листовки увеличивается и уменьшается, но созданный SVG является статичным. Я пытался реализовать много примеров, но я застрял ... Вот мой код:

 var map = L.map('map', {
        center: [52.52, 13.5],
        zoom: 11,
        zoomControl: true
    });

mapLink = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a>contributors'
        }).addTo(map);

    // Add an SVG element to Leaflet’s overlay pane
    var w = 950;
    var h = 600;
    var centered;
    var formatC = d3.format(",.0f");
    var formatD = d3.format("+,.0f");

    var immin, immax, exmin, exmax;

    var colors = ["#EDF8FB", "#41083E"];
    var immdomain = [24431, 537148];
    var emmdomain = [20056, 566986];

    var circleSize = d3.scale.linear().range([0, 25000]).domain([0, 137175]);
    var lineSize = d3.scale.linear().range([2, 25]).domain([0, 35000]);
    var fillcolor = d3.scale.linear().range(colors).domain(immdomain);

    //Define path generator
    var path = d3.geo.path()

    //Create SVG element
    var svg = d3.select(map.getPanes().overlayPane)
        .append("svg")
        .attr("width", w)
        .attr("height", h)
        .style("class", "background");

    var fp = d3.format(".1f");

    var g = svg.append("g").attr("class", "leaflet-zoom-hide");



    // This is the function that transforms D3 svg output to the correct leaflet projection
        function projectPoint(x, y) {
            var point = map.latLngToLayerPoint(new L.LatLng(y, x));
            this.stream.point(point.x, point.y);
        }

    //initialize html tooltip
    var tooltip = d3.select("#maincontainer")
        .append("div")
        .attr("id", "tt")
        .style("z-index", "10")
        .style("position", "absolute")
        .style("visibility", "hidden");

    var tooltip2 = d3.select("#maincontainer")
        .append("div")
        .attr("id", "tt2")
        .style("z-index", "10")
        .style("position", "absolute")
        .style("visibility", "hidden");


    var coming, going;
        d3.csv("coming.csv", function(data) {
            coming = data;
       });

        d3.csv("going.csv", function(data) {
            going = data;

        d3.json("test.json", function(json) {
            var bounds = d3.geo.bounds(json)
            bottomLeft = bounds[0],
            topRight = bounds[1],
            rotLong = -(topRight[0]+bottomLeft[0])/2;
            center = [(topRight[0]+bottomLeft[0])/2+rotLong, (topRight[1]+bottomLeft[1])/2],

          //default scale projection
            projection = d3.geo.albers()
            .parallels([bottomLeft[1],topRight[1]])
            .rotate([rotLong,0,0])
            .translate([w/2,h/2])
            .center(center),

            bottomLeftPx = projection(bottomLeft),
            topRightPx = projection(topRight),
            scaleFactor = 1.00*Math.min(w/(topRightPx[0]-bottomLeftPx[0]), h/(-topRightPx[1]+bottomLeftPx[1])),

            projection = d3.geo.albers()
            .parallels([bottomLeft[1],topRight[1]])
            .rotate([rotLong,0,0])
            .translate([w/2,h/2])
            .scale(scaleFactor*0.975*1000)
            .center(center);

        path = d3.geo.path()
            .projection(projection);


        for (var i = 0; i < data.length; i++) {
            var dataName = data[i].state;
            var tempObj = {};
                for (var propt in data[i]) {
                    var valz = parseFloat(data[i][propt]);
                    tempObj[propt] = valz;
        } 
            //Find the corresponding state inside the GeoJSON
            for (var j = 0; j < json.features.length; j++) {
                var jsonState = json.features[j].properties.name;
                    if (dataName == jsonState) {
                        matched = true;
                        json.features[j].properties.state = dataName;
                        json.features[j].id = dataName;
                        json.features[j].abbrev = data[i].abbrev;
                        json.features[j].ind = i;

                        for (var propt in tempObj) {
                            if (!isNaN(tempObj[propt])) {
                                json.features[j].properties[propt] = tempObj[propt];
                            }
                        }
                        break;
                    }
                } 
        }

        //Bind data and create one path per GeoJSON feature
            g.selectAll("path")
                .data(json.features)
                .enter()
                .append("path")
                .attr("class", "state")
                .attr("id", function(d) {
                    return d.properties.state;
                })
                .attr("d", path)
                .attr("stroke-width", 0.5)
                .style("stroke", "#666")
                .style("fill", "#fff");

            g.selectAll("circle")
                .data(json.features)
                .enter().append("circle")
                .attr("cx", function(d) {
                    var centname = d.properties.name;
                    var ctroid;
                        ctroid = path.centroid(d)[0];
                            return ctroid;
                })
                .attr("cy", function(d) {
                var centname = d.properties.name;
                var ctroid;
                    ctroid = path.centroid(d)[1]; 
                        return ctroid;
                })
                .attr("r", function(d) {
                var diff = d.properties.total_imm - d.properties.total_emm;
                return circleSize(Math.sqrt(Math.abs(diff) / Math.PI));
                })
                .attr("class", "circ")
                .attr("id", function(d) {
                    return d.abbrev;
                })
                .attr("fill", function(d) {
                    var diff = d.properties.total_imm - d.properties.total_emm;
                    if (diff > 0) {
                        return "#65a89d";
                    } 
                    else {
                        return "#a96a46";
                    }
                })
                .attr("fill-opacity", "0.5")
                .attr("stroke", "#fff")
                .attr("stroke-weight", "0.5")
                .on("mouseover", function(d) {
                    return toolOver(d, this);
                })
                .on("mousemove", function(d) {
                    var m = d3.mouse(this);
                        mx = m[0];
                        my = m[1];
                    return toolMove(mx, my, d);
                })
                .on("mouseout", function(d) {
                    return toolOut(d, this);
                })
                .on("click", function(d) {
                    clicked(d)
                });
            });
        });

        function toolOver(v, thepath) {
            d3.select(thepath).style({
                "fill-opacity": "0.7",
                "cursor": "pointer"
            });
            return tooltip.style("visibility", "visible");
        };

        function toolOut(m, thepath) {
            d3.select(thepath).style({
                "fill-opacity": "0.5",
                "cursor": ""
            });
            return tooltip.style("visibility", "hidden");
        };

        function toolMove(mx, my, data) {
            if (mx < 120) {
                mx = 120
            };
            if (my < 40) {
                my = 40
            };
            return tooltip.style("top", my + -140 + "px").style("left", mx - 120 + "px").html("<div id='tipContainer'><div id='tipLocation'><b>" + data.id + "</b></div><div id='tipKey'>Migration in: <b>" + formatC(data.properties.total_imm) + "</b><br>Migration out: <b>" + formatC(data.properties.total_emm) + "</b><br>Net migration: <b>" + formatC((data.properties.total_imm - data.properties.total_emm)) + "</b></div><div class='tipClear'></div> </div>");
        };

        function toolOver2(v, thepath) {
            d3.select(thepath).style({
                "opacity": "1",
                "cursor": "pointer"
            });
            return tooltip2.style("visibility", "visible");
        };

        function toolOut2(m, thepath) {
            d3.select(thepath).style({
                "opacity": "0.5",
                "cursor": ""
            });
            return tooltip2.style("visibility", "hidden");
        };

        function toolMove2(mx, my, home, end, v1, v2) {
            var diff = v1 - v2;
            if (mx < 120) {
                mx = 120
            };
            if (my < 40) {
                my = 40
            };
            return tooltip2.style("top", my + -140 + "px").style("left", mx - 120 + "px").html("<div id='tipContainer2'><div id='tipLocation'><b>" + home + "/" + end + "</b></div><div id='tipKey2'>Migration, " + home + " to " + end + ": <b>" + formatC(v2) + "</b><br>Migration, " + end + " to " + home + ": <b>" + formatC(v1) + "</b><br>Net change, " + home + ": <b>" + formatD(v1 - v2) + "</b></div><div class='tipClear'></div> </div>");
        };

        function clicked(selected) {

            var selname = selected.id;
            var homex = path.centroid(selected)[0];
            var homey = path.centroid(selected)[1];
            g.selectAll(".goingline")
                .attr("stroke-dasharray", 0)
                .remove()
            g.selectAll(".goingline")
                .data(going)
                .enter().append("path")
                .attr("class", "goingline")
                .attr("d", function(d, i) {
                    var abb = d.abbrev;     
                    var finalval = coming[i][selname] - going[i][selname];
                    var theState = d3.select("#" + abb); 
                    if (!isNaN(finalval)) {
                        var startx = path.centroid(theState[0][0].__data__)[0];
                        var starty = path.centroid(theState[0][0].__data__)[1];
                        if (finalval > 0) {
                            return "M" + startx + "," + starty + " Q" + (startx + homex) / 2 + " " + (starty + homey) / 1.5 + " " + homex + " " + homey;
                        } 
                        else {
                            return "M" + homex + "," + homey + " Q" + (startx + homex) / 2 + " " + (starty + homey) / 2.5 + " " + startx + " " + starty;
                        }
                    }
                })
                .call(transition)
                .attr("stroke-width", function(d, i) {
                    var finalval = coming[i][selname] - going[i][selname]; 
                        return lineSize(parseFloat(Math.abs(finalval)));
                })
                .attr("stroke", function(d, i) {
                    var finalval = coming[i][selname] - going[i][selname];
                    if (finalval > 0) {
                        return "#65a89d";
                    }
                    else {
                        return "#a96a46";
                    }
                    })
                .attr("fill", "none")
                .attr("opacity", 0.5)
                .attr("stroke-linecap", "round")
                .on("mouseover", function(d){
                    return toolOver2(d, this);
                })
                .on("mousemove", function(d, i){
                    var m = d3.mouse(this);
                    mx = m[0];
                    my = m[1];
                    return toolMove2(mx, my, selname, d.state, coming[i][selname], going[i][selname]);
                })
                .on("mouseout", function(d) {
                    return toolOut2(d, this);
                });
        }

        function transition(path) {
            path.transition()
                .duration(1500)
                .attrTween("stroke-dasharray", tweenDash);
           }

        function tweenDash() {
            var l = this.getTotalLength(),
                i = d3.interpolateString("0," + l, l + "," + l);
            return function(t) {
                return i(t);
            };
        }

Я все еще очень плохо знаком с d3 js. Я уверен, что моя проблема не большая, но мне действительно нужна помощь в этом.

...