Показать подсказку на карте D3 - PullRequest
0 голосов
/ 28 августа 2018

Я создал базовую карту, используя D3 с country geojson . Вот демоверсия .

Теперь, когда пользователь нажимает на любую координату на карте, я показываю информацию о погоде во всплывающей подсказке со значком погоды в качестве маркера.

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);
    });

Теперь проблема в том, что всплывающая подсказка остается в абсолютной позиции относительно тела (она остается в точной позиции на экране, которая вводит в заблуждение, если мы перемещаем и масштабируем карту), тогда как я хочу, чтобы подсказка была относительно координата, нажатая на карту, и должна быть зафиксирована по нажатой координате, независимо от того, где мы масштабируем или панорамируем карту, аналогично в этом примере (короче говоря, я хочу, чтобы подсказка работала аналогично типичным маркерам булавок на карте) ).

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Мне удалось сделать это с помощью CSS и следующих фрагментов:

var tooltipDiv = d3.select("body").append("div")    
    .attr("class", "tooltip")               
    .style("opacity", 0);

div.tooltip {   
    position: absolute;         
    text-align: center;         
    width: 80px;                    
    height: 28px;                   
    padding: 2px;               
    font: 12px sans-serif;      
    background: lightsteelblue; 
    border: 0px;        
    border-radius: 8px;         
    pointer-events: none;           
}

... а затем в svgs,

    .on("mouseover", function(d) {      
        tooltipDiv.transition()     
            .duration(200)      
            .style("opacity", .9);      
        tooltipDiv.html(d.vessel_name)  
            .style("left", (d3.event.pageX) + "px")     
            .style("top", (d3.event.pageY - 28) + "px");    
        })                  
    .on("mouseout", function(d) {       
        div.transition()        
            .duration(500)      
            .style("opacity", 0);   
    })

Определенно несовершенное решение, но, надеюсь, оно поможет. Полный источник:

Демо-версия:

http://Ares513.github.io/04-MapsAndViews/

Источник:

https://github.com/Ares513/MapsAndViews

0 голосов
/ 03 сентября 2018

Вы должны добавить элемент в SVG карты, а не тело. как это:

svg.select("#map")
   .append("text")
   .data(json)
   .classed("geopath", true);
...