[Chartjs]-Chartjs: Need help on drawing a vertical line when hovering cursor

14👍

You can use the Plugin Core API that offers different hooks to perform custom code. The simplest way would be to define an inline plugin and draw the line directly on the canvas through the CanvasRenderingContext2D. I would use the afterDraw hook as follows:

plugins: [{
  afterDraw: chart => {
    if (chart.tooltip?._active?.length) {
      let x = chart.tooltip._active[0].element.x;
      let yAxis = chart.scales.y;
      let ctx = chart.ctx;
      ctx.save();
      ctx.beginPath();
      ctx.moveTo(x, yAxis.top);
      ctx.lineTo(x, yAxis.bottom);
      ctx.lineWidth = 1;
      ctx.strokeStyle = 'rgba(0, 0, 255, 0.4)';
      ctx.stroke();
      ctx.restore();
    }
  }
}]

Please take a look at your amended code and see hot it works.

<body>
  <div class="chart-container">
    <canvas id="myChart"></canvas>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/chart.js@3.3.2/dist/chart.min.js"></script>

  <script>  
    
    var ctx = document.getElementById('myChart');
    BuildChart();

    function BuildChart() {

      var myChart = new Chart(ctx, {
        plugins: [{
          afterDraw: chart => {
            if (chart.tooltip?._active?.length) {               
               let x = chart.tooltip._active[0].element.x;             
               let yAxis = chart.scales.y;
               let ctx = chart.ctx;
               ctx.save();
               ctx.beginPath();
               ctx.moveTo(x, yAxis.top);
               ctx.lineTo(x, yAxis.bottom);
               ctx.lineWidth = 1;
               ctx.strokeStyle = 'rgba(0, 0, 255, 0.4)';
               ctx.stroke();
               ctx.restore();
            }
          }
        }],
        data: {
          labels: ['1', '2', '2562-3', '4', '5', '2562-6', '7', '8', '2562-9', '10', '11', '2562-12',
            '1', '2', '2563-3', '4', '5', '2563-6', '7', '8', '2563-9', '10', '11', '2563-12',
            '1', '2', '2564-3', '4', '5', '2564-6', '7', '8', '2564-9', '10', '11', '2564-12'],
          datasets: [{
            type: 'line',
            label: 'Price(THB)',
            data: [4.20, 4.30, 4.10, 3.90, 3.30, 3.40, 3.30, 3, 2.8, 2.2, 2.2, 2.2,
              2.0, 1.7, 1.4, 2.2, 3, 3.1, 3.6, 4.3, 5.1, 5, 4.8, 4.9,
              6, 6.2, 6.3, 7, 9.5, 10.3, NaN, NaN, NaN, NaN, NaN, NaN],
            backgroundColor: 'rgba(71, 198, 241, 1)',
            borderColor: 'rgba(71, 198, 241, 1)',
            borderWidth: 2,
            tension: 0,
            pointRadius: 0,
          },
          {
            type: 'line',
            label: 'FV Price(THB)',
            data: [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 1.9,
              NaN, NaN, 2.47, NaN, NaN, 3.87, NaN, NaN, 4.75, NaN, NaN, 6.16,
              NaN, NaN, 10.07, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN],
            backgroundColor: 'rgb(108, 113, 114, 0.7)',
            borderColor: 'rgb(108, 113, 114, 0.7)',
            borderWidth: 2,
            borderDash: [10, 5],
            tension: 0,
            pointRadius: 0,
          },
          {
            label: 'Revenue(MillionTHB)',
            data: [NaN, NaN, 482.97, NaN, NaN, 546.19, NaN, NaN, 590.11, NaN, NaN, 611.61,
              NaN, NaN, 656.77, NaN, NaN, 1033.46, NaN, NaN, 916.43, NaN, NaN, 1399.30,
              NaN, NaN, 1287.47, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN],
            backgroundColor: 'rgb(255, 153, 51, 0.2)',
            borderColor: 'rgb(255, 153, 51, 0.2)',
            borderWidth: 1,
            borderDash: [10, 5],
            type: 'bar',
            yAxisID: 'y1',
          },
          {
            label: 'Profit(MillionTHB)',
            data: [NaN, NaN, 11.65, NaN, NaN, 9.43, NaN, NaN, 27.54, NaN, NaN, 13.36,
              NaN, NaN, 30.27, NaN, NaN, 55.26, NaN, NaN, 56.16, NaN, NaN, 59.40,
              NaN, NaN, 81.59, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN],
            backgroundColor: 'rgb(255, 153, 51, 0.5)',
            borderColor: 'rgb(255, 153, 51, 0.5)',
            borderWidth: 1,
            borderDash: [10, 5],
            type: 'bar',
            yAxisID: 'y1',
          },
          {
            type: 'line',
            label: 'Forecast FV Price(THB)',
            data: [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, 10.07, NaN, NaN, 10.18, NaN, NaN, 11.05, NaN, NaN, 11.81],
            backgroundColor: 'rgb(108, 113, 114, 0.3)',
            borderColor: 'rgb(108, 113, 114, 0.3)',
            borderWidth: 2,
            borderDash: [10, 5],
            tension: 0,
            pointRadius: 0,
          },
          {
            label: 'Forecast Revenue(MillionTHB)',
            data: [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, NaN, NaN, NaN, 1300, NaN, NaN, 1500, NaN, NaN, 2000],
            backgroundColor: 'rgb(108, 113, 114, 0.1)',
            borderColor: 'rgb(108, 113, 114, 0.1)',
            borderWidth: 1,
            borderDash: [10, 5],
            type: 'bar',
            yAxisID: 'y1',
          },
          {
            label: 'Forecast Profit(MillionTHB)',
            data: [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN,
              NaN, NaN, NaN, NaN, NaN, 80, NaN, NaN, 80, NaN, NaN, 80],
            backgroundColor: 'rgb(108, 113, 114, 0.3)',
            borderColor: 'rgb(108, 113, 114, 0.3)',
            borderWidth: 1,
            borderDash: [10, 5],
            type: 'bar',
            yAxisID: 'y1',
          },
          ]
        },
        options: {
          scales: {
            y: {
              beginAtZero: true,
              title: {
                display: true,
                text: 'Price Per Share(THB)',
                //color: '#191',
                font: {
                  family: 'Kanit',
                  //size: 20,
                  //style: 'normal',
                  lineHeight: 1.2
                },
                padding: { top: 30, left: 0, right: 0, bottom: 0 }
              },
              position: 'right',
              //ticks: {
              //  // Include a dollar sign in the ticks
              //  callback: function (value, index, values) {
              //    return '$' + value;
              //  }
              //}
            },
            y1: {
              beginAtZero: true,
              title: {
                display: true,
                text: 'Revenue/Profit (Million THB)',
                //color: '#191',
                font: {
                  family: 'Kanit',
                  //size: 20,
                  //style: 'normal',
                  lineHeight: 1.2
                },
                padding: { top: 30, left: 0, right: 0, bottom: 0 }
              },
              type: 'linear',
              display: true,
              position: 'left',
              // grid line settings
              grid: {
                drawOnChartArea: false, // only want the grid lines for one axis to show up
              },
            },
            x: {
              grid: {
                drawOnChartArea: false, // only want the grid lines for one axis to show up
              },
            },
          },
          plugins: {
            title: {
              display: true,
              text: 'SET: WICE'
            }
          },
          interaction: {
            intersect: false,
            mode: 'index',
          },
          spanGaps: true,
        }
      });
    }

  </script>

</body>

</html>

Leave a comment