如何在 React D3 v4 条形图中添加工具提示

how to add tooltip in react d3 v4 bar chart

我必须在 mouseover.I 上的 React d3 v4 条形图上添加工具提示已经尝试了下面提到的自定义功能,

onMouseOverHandler(d){
   var tooltip = d3Select("body").append("div")   
    .attr("class", "tooltip")               
    .style("opacity", 0);

    tooltip.transition().duration(200).style("opacity", .9);      
    tooltip.html(d)  
    .style("left", d3Select(this).attr("cx") + "px")     
    .style("top", d3Select(this).attr("cy") + "px");

但它不起作用。谁能帮我解决这个问题。

谢谢, 阿伦小号

我在您对 this fork of the original GitHub repository 的评论中链接到的示例中添加了工具提示。

我创建了一个 Tooltip 组件。当然,请记住,这不一定是 "right" 或向使用 D3 的 React 应用程序添加工具提示的唯一方法。

我经历了以下步骤:

  1. 在跟踪数据的 Chart 组件中创建了状态,如果有的话,当前悬停了这些数据

  2. Bars 组件中创建了 onMouseOveronMouseOut 事件以确定哪个栏刚刚悬停或离开并将其传递给 Chart 组件设置新状态

  3. 将状态从 Chart 组件传回到我创建的 Tooltip 组件

Tooltip 组件如下所示:

export default ({hoveredBar, scales}) => {
  const { xScale, yScale } = scales
  const styles = {
    left: `${xScale(hoveredBar.title) - 30}px`,
    top: `${yScale(hoveredBar.value)}px`
  }

  return (
    <div className="Tooltip" style={styles}>
      <table>
        <thead>
          <tr>
            <th colSpan="2">{hoveredBar.title}</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colSpan="1">Bodies</td>
            <td colSpan="1">{hoveredBar.value}</td>
          </tr>
          <tr>
            <td colSpan="1">Year</td>
            <td colSpan="1">{hoveredBar.year}</td>
          </tr>
        </tbody>
      </table>
    </div>
  )
}

我在 Chart 组件中使用了它,并将当前悬停的栏跟踪为状态:

class Chart extends Component {
  constructor(props) {
    super(props)
    this.xScale = scaleBand()
    this.yScale = scaleLinear()

    this.state = {
      hoveredBar: null
    }
  }

  render() {
    const margins = { top: 50, right: 20, bottom: 100, left: 60 }
    const svgDimensions = {
      width: Math.max(this.props.parentWidth, 300),
      height: 500
    }

    const maxValue = Math.max(...data.map(d => d.value))

    const xScale = this.xScale
      .padding(0.5)
      .domain(data.map(d => d.title))
      .range([margins.left, svgDimensions.width - margins.right])

    const yScale = this.yScale
      .domain([0, maxValue])
      .range([svgDimensions.height - margins.bottom, margins.top])

    return (
      <div className="Chart">
        <svg width={svgDimensions.width} height={svgDimensions.height}>
          <Axes
            scales={{ xScale, yScale }}
            margins={margins}
            svgDimensions={svgDimensions}
          />
          <Bars
            scales={{ xScale, yScale }}
            margins={margins}
            data={data}
            maxValue={maxValue}
            svgDimensions={svgDimensions}
            onMouseOverCallback={datum => this.setState({hoveredBar: datum})}
            onMouseOutCallback={datum => this.setState({hoveredBar: null})}
          />
        </svg>
        { this.state.hoveredBar ?
          <Tooltip
            hoveredBar={this.state.hoveredBar}
            scales={{ xScale, yScale }}
          /> :
          null
        }
      </div>
    )
  }
}

然后我在 Bars 组件中设置了 onMouseOveronMouseOut 事件:

export default class Bars extends Component {
  constructor(props) {
    super(props)

    this.colorScale = scaleLinear()
      .domain([0, this.props.maxValue])
      .range(['#F3E5F5', '#7B1FA2'])
      .interpolate(interpolateLab)
  }

  render() {
    const { scales, margins, data, svgDimensions } = this.props
    const { xScale, yScale } = scales
    const { height } = svgDimensions

    const bars = (
      data.map(datum =>
        <rect
          key={datum.title}
          x={xScale(datum.title)}
          y={yScale(datum.value)}
          height={height - margins.bottom - scales.yScale(datum.value)}
          width={xScale.bandwidth()}
          fill={this.colorScale(datum.value)}
          onMouseOver={() => this.props.onMouseOverCallback(datum)}
          onMouseOut={() => this.props.onMouseOutCallback(null)}
        />,
      )
    )

    return (
      <g>{bars}</g>
    )
  }
}

在这里我描述了相同问题的解决方案。

结果看了this