1

I have used @nivo/bar for plotting bar charts in my react application. added line to display average value. on bars, the tooltip is working fine. I want to add a tooltip when the user hover over the line to show the average value.attached image

1 Answers1

4

I am not sure if anyone will ever need to implement similar functionality. but I did some research on this one, here is the answer to my own questions:

const CustomTagretLine = ({ props }) => {
const { bars } = props
const { showTooltipAt, hideTooltip } = useTooltip()


//show tooltip on mouse enter
const handleMouseEnter = (point) => {
  showTooltipAt(
    props.tooltip(point),
    [point.x + props.margin.left, point.y + props.margin.top],
    'top'
  )
}

//move tooltip with mouse position
const handleMouseMove = (point) => {
  showTooltipAt(
    props.tooltip(point),
    [point.x + props.margin.left, point.y + props.margin.top],
    'top'
  )
}

const handleMouseLeave = () => {
  hideTooltip()
}

return (
  <>
    {bars.map((bar, idx) => (
      <>
        {bar.height && (
          <line
            onMouseOver={() =>
              handleMouseEnter({
                x: bar.x - 5,
                y: props.yScale(bar?.data?.data?.avgVal || 0), //whatever you want
                absX: bar.x - 5 + 70,
                absY: props.yScale(bar?.data?.data?.avgVal || 0) + 50,
                width: 70,
                height: 4,
                data: {
                  ...bar?.data?.data,
                  isAvg: true,
                },
                formattedValue: formatNumber(
                  parseInt(bar?.data?.data?.avgVal) || 0
                ),
              })
            }
            onMouseLeave={() =>
              handleMouseLeave({
                x: bar.x - 5,
                y: props.yScale(bar?.data?.data?.avgVal || 0), //whatever you want
                absX: bar.x - 5 + 70,
                absY: props.yScale(bar?.data?.data?.avgVal || 0) + 50,
                width: 70,
                height: 4,
                data: {
                  ...bar?.data?.data,
                  isAvg: true,
                },
                formattedValue: formatNumber(
                  parseInt(bar?.data?.data?.avgVal) || 0
                ),
              })
            }
            onMouseMove={() =>
              handleMouseMove({
                x: bar.x - 5,
                y: props.yScale(bar?.data?.data?.avgVal || 0), //whatever you want
                absX: bar.x - 5 + 70,
                absY: props.yScale(bar?.data?.data?.avgVal || 0) + 50,
                width: 70,
                height: 4,
                data: {
                  ...bar?.data?.data,
                  isAvg: true,
                },
                formattedValue: formatNumber(
                  parseInt(bar?.data?.data?.avgVal) || 0
                ),
              })
            }
            key={idx}
            opacity="1"
            x1={bar.x - 5}
            x2={bar.x + bar.width + 5}
            y1={props.yScale(bar?.data?.data?.avgVal || 0)}
            y2={props.yScale(bar?.data?.data?.avgVal || 0)}
            stroke="#000000"
            strokeWidth="3"
          ></line>
        )}
      </>
    ))}
  </>
)}

CustomTargetLine is custom layer, which can be added like this in bar

layers={[
      'grid',
      'axes',
      'bars',
      'legends',
      'annotations',
      (props) => <CustomTagretLine props={props} />,
    ]} 

refrence: https://nivo.rocks/bar/