如何在反应d3 v4条形图中添加工具提示

时间:2018-04-02 12:17:33

标签: reactjs d3.js charts tooltip react-component

我必须在mouseover上添加反应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");

但它不起作用。有人可以帮我这个。

谢谢, Arun S

2 个答案:

答案 0 :(得分:2)

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

我创建了一个Tooltip组件。当然,请记住,这不一定是"对"或者只能将工具提示添加到使用D3的React应用程序。

我完成了以下步骤:

  1. Chart组件中创建的状态,用于跟踪当前悬停的栏(如果有)的数据

  2. onMouseOver组件中创建了onMouseOutBars个事件,以确定刚刚悬停或留下的栏,并将其传递到Chart组件设置新状态

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

  4. 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>
        )
      }
    }
    

    我在onMouseOver组件中设置了onMouseOutBars个事件:

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

答案 1 :(得分:0)

在这里,我描述了解决同一问题的方法。

https://stackoverflow.com/a/56674517/2903711

结果看起来this