首页 > 解决方案 > D3.js 工具提示文本停留在第一次观察 csv 时

问题描述

我正在尝试使用 d3.js 制作一个等值线地图,其中每个地图的路径都有一个在鼠标悬停时弹出的工具提示。我希望工具提示包含与路径相关的信息(在这种情况下,该信息将是给定地区的评级)。

我在下面使用的代码运行良好,但工具提示卡在输入 csv 的第一行。例如,如果我将鼠标悬停在 1 区,工具提示将正确显示该区的评级。当我将鼠标悬停在第 2 区时,它仍然只显示第 1 区的数据。即使我悬停的第一个区是第 1 区之外的一个区,也会出现这种情况。换句话说,工具提示会无限期地停留在第 1 区。

我在这里想念什么?提前感谢您的建议。

以下是ratings.csv数据示例:

"District","Rating"
"1","Hot"
"2","Cold"
"3","Cold"
"4","Hot"

这是一个 topojson 的示例:

"objects":{"districts":{"type":"GeometryCollection","geometries":[{"arcs":[[0,1,2]],"type":"Polygon","properties":{"District":"1"}}

这是html代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/topojson@3"></script>
</head>
<body>
    <div class="map-div">
        <script type="text/javascript">

            var width = 500;
            var height = 700;

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

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

            Promise.all([
                d3.json("districts.json"),  
                d3.csv("ratings.csv", function(d) {
                    return {
                        District: d.District,
                        Rating: d.Rating
                    }
                }) 
            ])
            .then(function(data){

            console.log(data)

            var conus = topojson.feature(data[0], {
                type:"GeometryCollection",
                geometries: data[0].objects.districts.geometries
            });

            var projection = d3.geoConicConformal()
                .parallels([38 + 20 / 60, 39 + 50 / 60])
                .rotate([122, 0])
                .fitExtent([[0,0],[630,700]], conus);

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

            var ratings_map = d3.map()

            data[1].forEach(function(d){
                ratings_map.set(d["District"], 
                {"Rating" : d["Rating"]});
                });

            var colorScale = d3.scaleOrdinal()
                .domain(["Cold", "Hot"])
                .range(["#11ede9", "#ed4011"]);

            map.selectAll("path")
            .data(topojson.feature(data[0], data[0].objects.districts).features)
            .enter()
            .append("path")
            .attr("d", path)
            .attr("class", "map-border")
            .on("mouseover", function(d) {
                d3.selectAll("path")
                    .style("opacity", .5)
                d3.select(this)
                    .style("cursor", "pointer")
                    .style("opacity", 1)
                    .style("stroke-width", "3px")
                    .style("stroke", "black")
                    .raise();
                })
            .on('mousemove', function (d) {
                tooltip.style("visibility", "visible")
                    .style("left", (d3.event.pageX - 550) + "px")
                    .style("top", (d3.event.pageY - 8) + "px")
                    .data(data[1])
                    .text(function(d) {
                        console.log(d)
                        return d.Rating
                    })
                tooltip.transition()
                    .duration(0)
                    .style("opacity", 1);
                })
            .on("mouseout", function(d) {
                tooltip.transition()
                    .style("visibility", "hidden");
                d3.selectAll("path")
                    .style("opacity", 1)
                d3.select(this)
                    .style("stroke-width", "0.75px")
                    .style("stroke", "white")
                    .style("opacity", 1)
                    .style("cursor", "default")
                    .attr("fill", function() {
                        let district = ratings_map.get(d.properties.DISTRICT);
                        return colorScale(district["Rating"]);
                });         
            }) 
            .attr("fill", function(d){ 
                let district = ratings_map.get(d.properties.DISTRICT);
                return colorScale(district["Rating"]);
            });
        });

</script>
</div>
</body>
</html>

标签: javascriptd3.js

解决方案


推荐阅读