Thursday 30 August 2018

Show tooltip on the D3 map

I've created a basic map using D3 with countries geojson. Here is the demo.

Now when the user clicks on any coordinate on the map, I am showing a weather info within a tooltip with weather icon as a marker.

countries = countriesGroup
    .selectAll("path")
    .data(json.features)
    .enter()
    .append("path")
    .attr("d", path)
    .attr("id", function(d, i) {
        return "country" + d.properties.iso_a3;
    })
    .attr("class", "country")
    // add a mouseover action to show name label for feature/country
    .on("mouseover", function(d, i) {
        d3.select("#countryLabel" + d.properties.iso_a3).style("display", "block");
    })
    .on("mouseout", function(d, i) {
        d3.select("#countryLabel" + d.properties.iso_a3).style("display", "none");
    })
    // add an onclick action to zoom into clicked country
    .on("click", function(d, i) {
        var eventLocation = d3.mouse(this);
        var coordinates = projection.invert(eventLocation);
        var proxy = "https://cors-anywhere.herokuapp.com/";
        var wetherInfoUrl =
            "https://api.darksky.net/forecast/c68e9aaf0d467528b9363e383bde6254/" + coordinates[1] + "," + coordinates[0] + "?exclude=minutely,hourly,daily";
        $.ajax({
            url: proxy + wetherInfoUrl,
            success: function(response) {
                tooltipDiv
                    .transition()
                    .duration(200)
                    .style("opacity", 0.9);
                tooltipDiv
                    .html('<h3>Dynamic Weather info: '+ response.currently.humidity +'</h3><br/><img src="https://darksky.net/images/weather-icons/' + response.currently.icon + '.png" alt="clear-night Icon" width="50" height="50">')
                    .style("left", (eventLocation[0] - 250) + "px")
                    .style("top", (eventLocation[1] - 100) + "px");
            }
        });
        d3.selectAll(".country").classed("country-on", false);
        d3.select(this).classed("country-on", true);
        boxZoom(path.bounds(d), path.centroid(d), 20);
    });

Now the issue is, the tooltip remains at the absolute position relative to the body (It stays at the exact position on the screen which is misleading if we pan and zoom the map) whereas I want the tooltip to be relative to the coordinate clicked on the map and should be fixed to the clicked coordinate no matter where we zoom or pan in the map, similar to this leaflet example (In short I want tooltip to behave similarly to the typical map pin markers).



from Show tooltip on the D3 map

No comments:

Post a Comment