我的工具提示卡在d3.js的底部

ryoqjall  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(168)

我尝试在d3.js中使用以下代码重新创建一个Map。这是一个交互式Map。当我将鼠标悬停在圆圈上时,它应该显示一个工具提示。但问题是我的工具提示不随鼠标移动。它卡在画布的底部。我尝试过改变样式。我不知道它是什么问题。有人能帮我解决这个问题吗?我使用的是d3版本4。

<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js and the geo projection plugin -->
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>

<!-- Create an element where the map will take place -->
<div id="my_dataviz"></div>

<style>
.circle:hover{
  stroke: black;
  stroke-width: 4px;
}
</style>

<script>

  // Size ?
  var width = 460
  var height = 400

  // The svg
  var svg = d3.select("#my_dataviz")
    .append("svg")
    .attr("width", width)
    .attr("height", height)

  // Map and projection
  var projection = d3.geoMercator()
      .center([4, 47])                // GPS of location to zoom on
      .scale(1020)                       // This is like the zoom
      .translate([ width/2, height/2 ])

  // Create data for circles:
  var markers = [
    {long: 9.083, lat: 42.149, name: "Corsica"}, // corsica
    {long: 7.26, lat: 43.71, name: "Nice"}, // nice
    {long: 2.349, lat: 48.864, name: "Paris"}, // Paris
    {long: -1.397, lat: 43.664, name: "Hossegor"}, // Hossegor
    {long: 3.075, lat: 50.640, name: "Lille"}, // Lille
    {long: -3.83, lat: 58, name: "Morlaix"}, // Morlaix
  ];

  // Load external data and boot
  d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson", function(data){

      // Filter data
      data.features = data.features.filter( function(d){return d.properties.name=="France"} )

      // Draw the map
      svg.append("g")
          .selectAll("path")
          .data(data.features)
          .enter()
          .append("path")
            .attr("fill", "#b8b8b8")
            .attr("d", d3.geoPath()
                .projection(projection)
            )
          .style("stroke", "black")
          .style("opacity", .3)

      // create a tooltip
      var Tooltip = d3.select("#my_dataviz")
        .append("div")
        .attr("class", "tooltip")
        .style("opacity", 1)
        .style("background-color", "white")
        .style("border", "solid")
        .style("border-width", "2px")
        .style("border-radius", "5px")
        .style("padding", "5px")

      // Three function that change the tooltip when user hover / move / leave a cell
      var mouseover = function(d) {
        Tooltip.style("opacity", 1)
      }
      var mousemove = function(d) {
        Tooltip
          .html(d.name + "<br>" + "long: " + d.long + "<br>" + "lat: " + d.lat)
          .style("left", (d3.mouse(this)[0]+10) + "px")
          .style("top", (d3.mouse(this)[1]) + "px")
      }
      var mouseleave = function(d) {
        Tooltip.style("opacity", 0)
      }

      // Add circles:
      svg
        .selectAll("myCircles")
        .data(markers)
        .enter()
        .append("circle")
          .attr("cx", function(d){ return projection([d.long, d.lat])[0] })
          .attr("cy", function(d){ return projection([d.long, d.lat])[1] })
          .attr("r", 14)
          .attr("class", "circle")
          .style("fill", "69b3a2")
          .attr("stroke", "#69b3a2")
          .attr("stroke-width", 3)
          .attr("fill-opacity", .4)
        .on("mouseover", mouseover)
        .on("mousemove", mousemove)
        .on("mouseleave", mouseleave)

  })

  </script>

nzk0hqpo

nzk0hqpo1#

工具提示的x,y坐标很好,只是缺少了position: absolute;的样式。我选择将其添加到下面代码片段中的<style>元素中,但您也可以在JS中使用.style()来完成。
我还选择将position: relative;添加到#my_dataviz,以保持工具提示相对于该容器的绝对位置。

<!-- Load d3.js and the geo projection plugin -->
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>

<!-- Create an element where the map will take place -->
<div id="my_dataviz"></div>

<style>
.circle:hover{
  stroke: black;
  stroke-width: 4px;
}

# my_dataviz {

 position: relative;
}
.tooltip {
  position: absolute;
}
</style>

<script>

  // Size ?
  var width = 460
  var height = 400

  // The svg
  var svg = d3.select("#my_dataviz")
    .append("svg")
    .attr("width", width)
    .attr("height", height)

  // Map and projection
  var projection = d3.geoMercator()
      .center([4, 47])                // GPS of location to zoom on
      .scale(1020)                       // This is like the zoom
      .translate([ width/2, height/2 ])

  // Create data for circles:
  var markers = [
    {long: 9.083, lat: 42.149, name: "Corsica"}, // corsica
    {long: 7.26, lat: 43.71, name: "Nice"}, // nice
    {long: 2.349, lat: 48.864, name: "Paris"}, // Paris
    {long: -1.397, lat: 43.664, name: "Hossegor"}, // Hossegor
    {long: 3.075, lat: 50.640, name: "Lille"}, // Lille
    {long: -3.83, lat: 58, name: "Morlaix"}, // Morlaix
  ];

  // Load external data and boot
  d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson", function(data){

      // Filter data
      data.features = data.features.filter( function(d){return d.properties.name=="France"} )

      // Draw the map
      svg.append("g")
          .selectAll("path")
          .data(data.features)
          .enter()
          .append("path")
            .attr("fill", "#b8b8b8")
            .attr("d", d3.geoPath()
                .projection(projection)
            )
          .style("stroke", "black")
          .style("opacity", .3)

      // create a tooltip
      var Tooltip = d3.select("#my_dataviz")
        .append("div")
        .attr("class", "tooltip")
        .style("opacity", 1)
        .style("background-color", "white")
        .style("border", "solid")
        .style("border-width", "2px")
        .style("border-radius", "5px")
        .style("padding", "5px")

      // Three function that change the tooltip when user hover / move / leave a cell
      var mouseover = function(d) {
        Tooltip.style("opacity", 1)
      }
      var mousemove = function(d) {
        Tooltip
          .html(d.name + "<br>" + "long: " + d.long + "<br>" + "lat: " + d.lat)
          .style("left", (d3.mouse(this)[0]+10) + "px")
          .style("top", (d3.mouse(this)[1]) + "px")
      }
      var mouseleave = function(d) {
        Tooltip.style("opacity", 0)
      }

      // Add circles:
      svg
        .selectAll("myCircles")
        .data(markers)
        .enter()
        .append("circle")
          .attr("cx", function(d){ return projection([d.long, d.lat])[0] })
          .attr("cy", function(d){ return projection([d.long, d.lat])[1] })
          .attr("r", 14)
          .attr("class", "circle")
          .style("fill", "69b3a2")
          .attr("stroke", "#69b3a2")
          .attr("stroke-width", 3)
          .attr("fill-opacity", .4)
        .on("mouseover", mouseover)
        .on("mousemove", mousemove)
        .on("mouseleave", mouseleave)

  })

  </script>

下面是另一个代码片段,它使用display: none;而不是修改opacity来隐藏工具提示。这修复了一个错误,即其中一个圆圈(例如,科西嘉)可能不再接收鼠标事件,因为工具提示位于它的顶部,尽管它是不可见的。

<!-- Load d3.js and the geo projection plugin -->
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>

<!-- Create an element where the map will take place -->
<div id="my_dataviz"></div>

<style>
.circle:hover{
  stroke: black;
  stroke-width: 4px;
}

# my_dataviz {

  position: relative;
}
.tooltip {
  position: absolute;
  display: none;
}
</style>

<script>

  // Size ?
  var width = 460
  var height = 400

  // The svg
  var svg = d3.select("#my_dataviz")
    .append("svg")
    .attr("width", width)
    .attr("height", height)

  // Map and projection
  var projection = d3.geoMercator()
      .center([4, 47])                // GPS of location to zoom on
      .scale(1020)                       // This is like the zoom
      .translate([ width/2, height/2 ])

  // Create data for circles:
  var markers = [
    {long: 9.083, lat: 42.149, name: "Corsica"}, // corsica
    {long: 7.26, lat: 43.71, name: "Nice"}, // nice
    {long: 2.349, lat: 48.864, name: "Paris"}, // Paris
    {long: -1.397, lat: 43.664, name: "Hossegor"}, // Hossegor
    {long: 3.075, lat: 50.640, name: "Lille"}, // Lille
    {long: -3.83, lat: 58, name: "Morlaix"}, // Morlaix
  ];

  // Load external data and boot
  d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson", function(data){

      // Filter data
      data.features = data.features.filter( function(d){return d.properties.name=="France"} )

      // Draw the map
      svg.append("g")
          .selectAll("path")
          .data(data.features)
          .enter()
          .append("path")
            .attr("fill", "#b8b8b8")
            .attr("d", d3.geoPath()
                .projection(projection)
            )
          .style("stroke", "black")
          .style("opacity", .3)

      // create a tooltip
      var Tooltip = d3.select("#my_dataviz")
        .append("div")
        .attr("class", "tooltip")
        .style("background-color", "white")
        .style("border", "solid")
        .style("border-width", "2px")
        .style("border-radius", "5px")
        .style("padding", "5px")

      // Three function that change the tooltip when user hover / move / leave a cell
      var mouseover = function(d) {
        Tooltip.style("display", "block")
      }
      var mousemove = function(d) {
        Tooltip
          .html(d.name + "<br>" + "long: " + d.long + "<br>" + "lat: " + d.lat)
          .style("left", (d3.mouse(this)[0]+10) + "px")
          .style("top", (d3.mouse(this)[1]) + "px")
      }
      var mouseleave = function(d) {
        Tooltip.style("display", "none")
      }

      // Add circles:
      svg
        .selectAll("myCircles")
        .data(markers)
        .enter()
        .append("circle")
          .attr("cx", function(d){ return projection([d.long, d.lat])[0] })
          .attr("cy", function(d){ return projection([d.long, d.lat])[1] })
          .attr("r", 14)
          .attr("class", "circle")
          .style("fill", "69b3a2")
          .attr("stroke", "#69b3a2")
          .attr("stroke-width", 3)
          .attr("fill-opacity", .4)
        .on("mouseover", mouseover)
        .on("mousemove", mousemove)
        .on("mouseleave", mouseleave)

  })

  </script>

相关问题