[Chartjs]-Chart.js Tooltip over the line not only over points

5👍

You can use the croshair plugin for this if you are still using v2 of the lib: https://chartjs-plugin-crosshair.netlify.app/

Live example:

var ctx = document.getElementById("myChart");

function generateDataset(shift, label, color) {

  function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  let data = [];
  let index = 0;

  while (index < 5) {
    data.push({
      x: index,
      y: getRandomInt(10, 40)
    });
    index++;
  }

  var dataset = {
    backgroundColor: color,
    borderColor: color,
    showLine: true,
    fill: false,
    pointRadius: 2,
    label: label,
    data: data,
    lineTension: 0,
    interpolate: true,
    xAxisID: 'x-axis-0'
  };
  return dataset;
}

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['A', 'B', 'C', 'D', 'E'],
    datasets: [
      generateDataset(0, "A", "red"),
      generateDataset(1, "B", "green")
    ]
  },
  options: {
    scales: {
      xAxes: [{
        display: true,
        type: 'linear',
        position: 'bottom',
        id: 'x-axis-0',
        ticks: {
          source: 'labels'
        }
      }]
    },
    tooltips: {
      mode: "interpolate",
      intersect: false,
      callbacks: {
        title: function(a, d) {
          // return a[0].xLabel.toFixed(2);
          return a[0].xLabel;
        },
        label: function(i, d) {
          return (
            d.datasets[i.datasetIndex].label + ": " + i.yLabel.toFixed(2)
          );
        }
      }
    },
    plugins: {
      crosshair: {
        line: {
          // Add alpha chanel so line becomes transparant so you dont see it
          color: '#ffffff00',
        },
        sync: {
          enabled: false
        }
      }
    }
  }
});
.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}
<html>

<body>
  <div class="myChartDiv">
    <canvas id="myChart" width="600" height="400"></canvas>
  </div>
  <script src="https://npmcdn.com/chart.js@2.9.4/dist/Chart.bundle.min.js"></script>
  <script src="https://unpkg.com/chartjs-plugin-crosshair@1.1.6/dist/chartjs-plugin-crosshair.js"></script>
</body>

</html>

If you are using V3 of the lib you will need to use a custom own plugin

Example:

// Options for the indicators
const indicatorOptions = {
  radius: 4, borderWidth: 1, borderColor: 'red', backgroundColor: 'transparent'
};

// Override getLabelAndValue to return the interpolated value
const getLabelAndValue = Chart.controllers.line.prototype.getLabelAndValue;
Chart.controllers.line.prototype.getLabelAndValue = function(index) {
  if (index === -1) {
    const meta = this.getMeta();
    const pt = meta._pt;
    const vScale = meta.vScale;
    return {
      label: 'interpolated',
      value: vScale.getValueForPixel(pt.y)
    };
  }
  return getLabelAndValue.call(this, index);
}

// The interaction mode
Chart.Interaction.modes.interpolate = function (chart, e, option) {
  const x = e.x;
  const items = [];
  const metas = chart.getSortedVisibleDatasetMetas();
  for (let i = 0; i < metas.length; i++) {
    const meta = metas[i];
    const pt = meta.dataset.interpolate({ x }, "x");
    if (pt) {
      const element = new Chart.elements.PointElement({...pt, options: {...indicatorOptions}});
      meta._pt = element;
      items.push({element, index: -1, datasetIndex: meta.index });
    } else {
      meta._pt = null;
    }
  }
  return items;
};

// Plugin to draw the indicators
Chart.register({
  id: 'indicators',
  afterDraw(chart) {
    const metas = chart.getSortedVisibleDatasetMetas();
    for (let i = 0; i < metas.length; i++) {
      const meta = metas[i];
      if (meta._pt) {
        meta._pt.draw(chart.ctx);
      }
    }    
  },
  afterEvent(chart, args) {
    if (args.event.type === 'mouseout') {
      const metas = chart.getSortedVisibleDatasetMetas();
      for (let i = 0; i < metas.length; i++) {
        metas[i]._pt = null;
      }
      args.changed = true;
    }
  }
})

var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
  type: "line",
  data: {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [
      {
        fill: true,
        label: "My First dataset",
        backgroundColor: "rgba(132, 0, 0, 1)",
        borderColor: "rgb(255, 99, 132)",
        data: [0, 10, 5, 2, 20, 30, 45]
      },
      {
        data: [30, 40, 50],
        label: 'My Second Dataset',
        fill: true,
        backgroundColor: "lightgreen",
        borderColor: "green"
      }
    ]
  },
  options: {
    interaction: {
      mode: "interpolate",
      intersect: false,
      axis: "x"
    },
    plugins: {
      tooltip: {
        position: 'nearest',
        displayColors: false,
      }
    }
  },
});
.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}
<h1>Interpolating line values</h1>
<div class="myChartDiv">
  <canvas id="myChart" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script>
</div>

Leave a comment