【问题标题】:how to add tooltip in react d3 v4 bar chart如何在反应 d3 v4 条形图中添加工具提示
【发布时间】:2018-04-02 12:17:32
【问题描述】:

我必须在鼠标悬停时在 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");

但它不起作用。有人可以帮我解决这个问题。

谢谢, 阿伦S

【问题讨论】:

  • 你研究过tippy.js吗?它可能会有所帮助,而不是自己写出来。
  • 你能把它放在 jsfiddle 或 plunker 中吗?如果我们无法重现问题,我们无法帮助您解决问题。
  • 嗨 Ryan,我只是想在下面提到的示例图表中添加工具提示,medium.com/@caspg/… 但我不知道如何添加它。

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


【解决方案1】:

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

我创建了一个Tooltip 组件。当然,请记住,这不一定是向使用 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>
    )
  }
}

【讨论】:

    【解决方案2】:

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

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

    结果看起来this

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 1970-01-01
      • 2013-09-15
      • 1970-01-01
      • 2020-10-24
      • 2018-11-24
      • 1970-01-01
      • 2017-08-12
      • 2013-12-02
      相关资源
      最近更新 更多