Hover Events in JavaScript

How to bind callback functions to hover events in D3.js-based JavaScript charts.


Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.

{
  points: [{
    curveNumber: 2,  // index in data of the trace associated with the selected point 
    pointNumber: 2,  // index of the selected point
    x: 5,        // x value
    y: 600,      // y value
    data: {/* */},       // ref to the trace as sent to Plotly.newPlot associated with the selected point
    fullData: {/* */},   // ref to the trace including all the defaults
   xaxis: {/* */},   // ref to x-axis object (i.e layout.xaxis) associated with the selected point
   yaxis: {/* */}    // ref to y-axis object " "
  }, {
    /* similarly for other selected points */
  }]
}
var myPlot = document.getElementById('myDiv'),
    hoverInfo = document.getElementById('hoverinfo'),
    N = 16,
    x = d3.range(N),
    y1 = d3.range(N).map( d3.random.normal() ),
    y2 = d3.range(N).map( d3.random.normal() ),
    data = [ { x:x, y:y1, type:'scatter', name:'Trial 1',
        mode:'markers', marker:{size:16} },
        { x:x, y:y2, type:'scatter', name:'Trial 2',
        mode:'markers', marker:{size:16} } ];
    layout = {
        hovermode:'closest',
        title: {text: 'Hover on Points'}
     };

Plotly.newPlot('myDiv', data, layout);

myPlot.on('plotly_hover', function(data){
    var infotext = data.points.map(function(d){
      return (d.data.name+': x= '+d.x+', y= '+d.y.toPrecision(3));
    });

    hoverInfo.innerHTML = infotext.join('<br/>');
})
 .on('plotly_unhover', function(data){
    hoverInfo.innerHTML = '';
});
var myPlot = document.getElementById('myDiv'),
    hoverInfo = document.getElementById('hoverinfo'),
    N = 16,
    x = d3.range(N),
    y1 = d3.range(N).map(d3.random.normal()),
    y2 = d3.range(N).map(d3.random.normal()),
    data = [{x:x, y:y1, type:'scatter', name:'Trial 1',
        mode:'markers', marker:{size:16}},
        {x:x, y:y2, type:'scatter', name:'Trial 2',
        mode:'markers', marker:{size:16}}],
    layout = {hovermode:'closest',
              title: {text: 'Hover on Points to see<br>Pixel Coordinates'}};

Plotly.newPlot('myDiv', data, layout);

myPlot.on('plotly_hover', function(data){
    var xaxis = data.points[0].xaxis,
        yaxis = data.points[0].yaxis;
    var infotext = data.points.map(function(d){
      return ('width: '+xaxis.l2p(d.x)+', height: '+yaxis.l2p(d.y));
    });

    hoverInfo.innerHTML = infotext.join('<br/>');
})
 .on('plotly_unhover', function(data){
    hoverInfo.innerHTML = '';
});

New in 3.5

By default, plotly_hover fires only when the cursor is over a trace. Set hoveranywhere to true in the layout, and the event also fires over empty plot space.

An event from empty space carries an empty points array. The event reports the cursor position in two forms. xvals and yvals hold data-space coordinates. xPixel and yPixel hold pixels from the top-left corner of the graph div.

plotly_unhover fires once when the cursor leaves the plot area.

var data = [{
  x: [1, 2, 3, 4, 5],
  y: [2, 4, 3, 5, 4],
  type: 'scatter',
  mode: 'markers',
  marker: {size: 14}
}];

var hoverPrompt = 'Hover anywhere in the plot area';

var layout = {
  title: {text: 'Hover Anywhere'},
  hovermode: 'closest',
  hoveranywhere: true,
  annotations: [{
    text: hoverPrompt,
    xref: 'paper',
    yref: 'paper',
    x: 0.02,
    y: 0.98,
    xanchor: 'left',
    yanchor: 'top',
    showarrow: false
  }]
};

Plotly.newPlot('myDiv', data, layout);

var hoverReadout = hoverPrompt;

// Redraw only when the text changes, because plotly_hover fires on every cursor move
function showHoverReadout(text) {
  if (text === hoverReadout) return;
  hoverReadout = text;
  Plotly.relayout('myDiv', {'annotations[0].text': text});
}

document.getElementById('myDiv').on('plotly_hover', function(eventData) {
  if (eventData.points.length) {
    var point = eventData.points[0];
    showHoverReadout('Over a point: x = ' + point.x + ', y = ' + point.y);
  } else {
    // points is empty over blank space, so read the cursor position from xvals and yvals
    showHoverReadout('Empty space: x = ' + eventData.xvals[0].toFixed(2) +
      ', y = ' + eventData.yvals[0].toFixed(2));
  }
});

document.getElementById('myDiv').on('plotly_unhover', function() {
  showHoverReadout(hoverPrompt);
});
var myPlot = document.getElementById('myDiv'),
    hoverButton = document.getElementById('hoverbutton'),
    N = 16,
    x = d3.range(N),
    y1 = d3.range(N).map( d3.random.normal() ),
    y2 = d3.range(N).map( d3.random.normal() ),
    data = [ { x:x, y:y1, type:'scatter', name:'Trial 1',
        mode:'markers', marker:{size:16} },
        { x:x, y:y2, type:'scatter', name:'Trial 2',
        mode:'markers', marker:{size:16} } ];
    layout = {
        hovermode:'closest',
        title: {text: 'Click "Go" button to trigger hover'}
     };

Plotly.newPlot('myDiv', data, layout);

myPlot.on('plotly_beforehover',function(){
    return false;
});

hoverButton.addEventListener('click', function(){
    var curve1 = Math.floor(Math.random()*2),
        curve2 = Math.floor(Math.random()*2),
        point1 = Math.floor(Math.random()*14),
        point2 = Math.floor(Math.random()*14);
    Plotly.Fx.hover('myDiv',[
        {curveNumber:curve1, pointNumber:point1},
        {curveNumber:curve2, pointNumber:point2}
    ]);
});
var myPlot = document.getElementById('myDiv'),
    N = 12,
    x1 = d3.range(N).map( d3.random.normal() ),
    x2 = d3.range(N).map( d3.random.normal() ),
    x3 = d3.range(N).map( d3.random.normal() ),
    y1 = d3.range(N).map( d3.random.normal() ),
    y2 = d3.range(N).map( d3.random.normal() ),
    y3 = d3.range(N).map( d3.random.normal() ),
    months = ['January', 'February', 'March', 'April',
              'May', 'June', 'July', 'August',
              'September', 'October', 'November', 'December']
    data = [{ x: x1, y: y1, text: months, type: 'scatter', name: '2014', hoverinfo: 'text+x+y',
              mode: 'markers', marker: {color: 'rgba(200, 50, 100, .7)', size: 16}
            },
            { x: x2, y: y2, text: months, type: 'scatter', name: '2015', hoverinfo: 'text+x+y',
             mode: 'markers', marker: {color: 'rgba(120, 20, 130, .7)', size: 16}
            },
            { x: x3, y: y3, text: months, type: 'scatter', name: '2016', hoverinfo: 'text+x+y',
             mode: 'markers', marker: {color: 'rgba(10, 180, 180, .8)', size: 16}
            }];
    layout = {
        hovermode:'closest',
        title: {text: 'Display Hover Info for Related Points'},
        xaxis:{zeroline:false, hoverformat: '.2r'},
        yaxis:{zeroline:false, hoverformat: '.2r'}
     };

Plotly.newPlot('myDiv', data, layout);

myPlot.on('plotly_hover', function (eventdata){
    var points = eventdata.points[0],
        pointNum = points.pointNumber;

    Plotly.Fx.hover('myDiv',[
        { curveNumber:0, pointNumber:pointNum },
        { curveNumber:1, pointNumber:pointNum },
        { curveNumber:2, pointNumber:pointNum },
    ]);
});
This is a more complex example that uses both hover, and click events to display traces. Take a look in the codepen javascript!