D3 + React工具提示未显示

ix0qys7i  于 2023-05-07  发布在  React
关注(0)|答案(1)|浏览(155)

我使用d3在html中构建了一个基本的热图,工具提示显示正确。我在React中使用了相同的代码,热图也在工作,鼠标悬停、鼠标移动和鼠标离开功能也在工作(数据准确地打印到控制台中),但无论我怎么尝试,我都无法让工具提示真正显示出来。任何帮助都将不胜感激
下面是我的代码--

import rd3 from 'react-d3-library';
import * as d3 from 'd3';
import React from 'react';
import data2 from '../data/hmap_current_year.csv';

const node = document.createElement('div');

 // set the dimensions and margins of the graph
 const margin = { top: 30, right: 60, bottom: 29, left: 60 },
 width = 1400 - margin.left - margin.right,
 height = 630 - margin.top - margin.bottom;

// append the svg object to the body of the page
const svg = d3
 .select(node)
 .append("svg")
 //add mobile-friendly
 .attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
//  .attr("width", width + margin.left + margin.right)
//  .attr("height", height + margin.top + margin.bottom)
 .append("g")
 .attr("transform", `translate(${margin.left},${margin.top})`);

d3.csv(data2).then(function (data) {
 const var0 = data.map(function (d0) {
     return {
         month: d3.timeParse("%Y-%m-%d")(d0.time).getMonth(),
         day: d3.timeParse("%Y-%m-%d")(d0.time).getDate(),
         value: d0.tmed
     }
 })

 const myGroups = Array.from({ length: 31 }, (_, i) => i + 1)
 const myMonths = [
    "Jan", 
    "Feb", 
    "Mar", 
    "Apr", 
    "May", 
    "Jun", 
    "Jul", 
    "Aug", 
    "Sep", 
    "Oct", 
    "Nov", 
    "Dec"
    ]

 // Build X scales and axis:
 const x = d3.scaleBand()
     .range([0, width])
     .domain(myGroups)
     .padding(0.01);
     svg.append("g")
     .attr("transform", `translate(0, ${height})`)
     .call(d3.axisBottom(x))
     .call(g => g.select(".domain").remove());

     svg.append("g")
     .call(d3.axisTop(x))
     .call(g => g.select(".domain").remove());

 // Build X scales and axis:
 const y = d3.scaleBand()
     .range([0, height])
     .domain(myMonths)
     .padding(0.01);
     svg.append("g")
     .call(d3.axisLeft(y))
     .call(g => g.select(".domain").remove());
     svg.append("g")
     .call(d3.axisRight(y))
     .attr("transform", `translate(${width}, 0)`)
     .call(g => g.select(".domain").remove());

 // Build color scale
 const myColor = d3.scaleQuantile()
     .domain([0, 5, 20, 40, 60, 80, 95, 100])
     .range([
        "#08306B", 
        "#2171B5", 
        "#6BAED6", 
        "#FFFFFF", 
        "#FCBBA1", 
        "#FA6A4A", 
        "#CB181D"
    ]);

 // create a tooltip
 const tooltip = d3.select(node)
     .append("div")
     .style("opacity", 0)
     .attr("class", "tooltip")
     .style("background-color", "white")
     .style("border", "solid")
     .style("border-width", "2px")
     .style("border-radius", "5px")
     .style("padding", "5px")
     .style("margin-bottom", '51px')

 // Three function that change the tooltip when user hover / move / leave a cell
 const mouseover = function (event, d) {
         tooltip
         .style("opacity", 1)
         d3.select(this)
         .style("stroke", "black")
         .style("opacity", 1)
 }
 const mousemove = function (event, d) {
         tooltip
         .html("The exact value of<br>this cell is: " + d.value)
         //accessing values correctly
         console.log(d.value, 'HELLO')
         .style("left", (event.x) / 2 + "px")
         .style("top", (event.y) / 2 + "px")
 };
 const mouseleave = function (event, d) {
         tooltip
         .style("opacity", 0)
         d3.select(this)
         .style("stroke", "none")
         .style("opacity", 1)
 }

 svg.selectAll()
     .data(var0)
     .join("rect")
     .attr("x", function (d) { return x(d.day) })
     .attr("y", function (d) { return y(myMonths[d.month]) })
     .attr("width", x.bandwidth())
     .attr("height", y.bandwidth())
     .style("fill", function (d) { return myColor(d.value) })
     .style("stroke", "none")
     .on("mouseover", mouseover)
     .on("mousemove", mousemove)
     .on("mouseleave", mouseleave)
});

const RD3Component = rd3.Component;
class HeatmapInteractive extends React.Component {
    constructor(props) {
        super(props);
        this.state = {d3: ''}
    }
    componentDidMount() {
        this.setState({d3: node});
    }
    render() {
        return (
            <div>
                <RD3Component data={this.state.d3}/>
            </div>
        )
    }
}
export default HeatmapInteractive;
qacovj5a

qacovj5a1#

在这里,您已经完美地完成了最初定义工具提示的工作

const tooltip = d3.select(node)
     .append("div")
     .style("opacity", 0)
     .attr("class", "tooltip")
     .style("background-color", "white")
     .style("border", "solid")
     .style("border-width", "2px")
     .style("border-radius", "5px")
     .style("padding", "5px")
     .style("margin-bottom", '51px')

但是,当鼠标悬停时,您不必d3.select在**mouseovermouseleave**状态下使用www.example.com(this)选择任何节点

你写了这个

const mouseover = function (event, d) {
         tooltip
         .style("opacity", 1)
         d3.select(this)
         .style("stroke", "black")
         .style("opacity", 1)
 }

您可以简单地从链接中删除d3.select(节点)

代替这样做,你可以简单地改变只有不透明度在鼠标悬停

const mouseover = function(event, d) {
    tooltip.style("opacity", 1)
  }

如果是鼠标离开就反转

const mouseleave = function(event, d) {
    tooltip.style("opacity", 0)
  }

如果是mousemove,则必须根据鼠标值添加htmlpostion properties以实现工具提示的动态浮动,如
注意还有一件事不要在链接中间使用控制台,这可能会破坏链接,如果你已经测试过它,那么必须删除它,否则它将无法工作

const mousemove = function (event, d) {
         tooltip
         .html("The exact value of<br>this cell is: " + d.value)
         .style("opacity", 1)
         .style("left", (event.x) + 20 + "px")
         .style("top", (event.y) + 20 + "px")
 };

我希望这个答案能澄清你

相关问题