Select Page

Here is a piece of code I developed for one of my projects where I needed to customize ChartJS with vertical line on hovered points and custom tooltip.


View DEMO

Open demo in a full window – https://demos.webdevpuneet.com/chartjs-verticle-line/index.html

CODE

<!doctype html>
<html lang="en">
  <head>
    <!-- Meta Tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="robots" content="INDEX,FOLLOW"/>

    <title>Site Title</title>
    <meta name="description" content="Site Description"/>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800" rel="stylesheet">

    <!-- Scripts -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>

    <!-- Framework + Styles -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css">
    <link rel="stylesheet" href="./assets/css/page.css">
  </head>
  <body class="page-home">
    <div class="container">


      <section class="bink-investgraph">
        <div class="bink-investgraph__title">
          <a style="color: #000;text-decoration:none;" href="https://webdevpuneet.com"><img src="./assets/img/bink-img4.png"> ChartJS – Vertical line on points and custom tooltip</a>
        </div>
        <canvas id="ctx"></canvas>
        <script>

            Chart.defaults.LineWithLine = Chart.defaults.line;

            Chart.controllers.LineWithLine = Chart.controllers.line.extend({
             draw: function(ease) {
                Chart.controllers.line.prototype.draw.call(this, ease);

                if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
                   var activePoint = this.chart.tooltip._active[0],
                       ctx = this.chart.ctx,
                       x = activePoint.tooltipPosition().x,
                       y = activePoint.tooltipPosition().y,
                       topY = activePoint.tooltipPosition().y - 20,
                       bottomY = this.chart.scales['y-axis-0'].bottom;

                   // draw line
                   ctx.save();
                   ctx.beginPath();
                   ctx.moveTo(x-5 , topY);
                   ctx.lineTo(x, bottomY);
                   ctx.lineWidth = 10;
                   ctx.strokeStyle = '#ff0000';
                   ctx.stroke();
                   ctx.restore();

                   // draw Circle
                   ctx.save();
                   ctx.beginPath();
                   ctx.arc(x-5.5 , topY + 5, 7.5, 0, 2 * Math.PI);
                   ctx.fillStyle ="#ff0000";
                   ctx.fill();
                   ctx.stroke();

                }
             }
            });

            var chart = new Chart(ctx, {
             type: 'LineWithLine',
             data: {
                 labels: ['20-JUN-1990', '21-JUN-1990', '25-JUN-1990', '26-JUN-1990', '21-JUL-1990', '22-AUG-1990', '25-SEP-1990', '20-OCT-1990', '21-NOV-1990', '21-DEC-1990', '1-JAN-1991'],
                 datasets: [{
                   data: [80, 70, 90, 70, 90, 40, 30, 70, 80, 90, 70],
                   label: '%',
                   backgroundColor:'rgba(21, 92, 84, 0.75)',
                   borderColor:'rgba(255, 0, 0, 1)',
                   borderWidth: 2,
                }]
             },

             options: {
               tooltips: {
                 // Disable the on-canvas tooltip
                 enabled: false,
                 mode: 'index',
                 intersect: false,

                 custom: function(tooltipModel) {
                     // Tooltip Element
                     var tooltipEl = document.getElementById('chartjs-tooltip');

                     // Create element on first render
                     if (!tooltipEl) {
                         tooltipEl = document.createElement('div');
                         tooltipEl.id = 'chartjs-tooltip';
                         tooltipEl.innerHTML = '<table class="bink-calc__tooltip"></table>';
                         document.body.appendChild(tooltipEl);
                     }

                     // Hide if no tooltip
                     if (tooltipModel.opacity === 0) {
                         tooltipEl.style.opacity = 0;
                         return;
                     }

                     // Set caret Position
                     tooltipEl.classList.remove('above', 'below', 'no-transform');
                     if (tooltipModel.yAlign) {
                         tooltipEl.classList.add(tooltipModel.yAlign);
                     } else {
                         tooltipEl.classList.add('no-transform');
                     }

                     function getBody(bodyItem) {
                         return bodyItem.lines;
                     }

                     // Set Text
                     if (tooltipModel.body) {
                         var titleLines = tooltipModel.title || [];
                         var bodyLines = tooltipModel.body.map(getBody);

                         var innerHtml = '<thead>';

                         titleLines.forEach(function(title) {
                             innerHtml += '<tr><th>' + title + '</th></tr>';
                         });
                         innerHtml += '</thead><tbody>';

                         bodyLines.forEach(function(body, i) {
                             var colors = tooltipModel.labelColors[i];
                             var style = 'background:' + colors.backgroundColor;
                             style += '; border-color:' + colors.borderColor;
                             style += '; border-width: 2px';
                             var span = '<span style="' + style + '"></span>';
                             innerHtml += '<tr><td>' + span + body + '</td></tr>';
                         });
                         innerHtml += '</tbody>';

                         var tableRoot = tooltipEl.querySelector('table');
                         tableRoot.innerHTML = innerHtml;
                     }

                     // `this` will be the overall tooltip
                     var position = this._chart.canvas.getBoundingClientRect();

                     // Display, position, and set styles for font
                     tooltipEl.style.opacity = 1;
                     tooltipEl.style.position = 'absolute';
                     tooltipEl.style.left = position.left + window.pageXOffset + tooltipModel.caretX + 'px';
                     tooltipEl.style.top = position.top + window.pageYOffset + tooltipModel.caretY + 'px';
                     tooltipEl.style.fontFamily = tooltipModel._bodyFontFamily;
                     tooltipEl.style.fontSize = tooltipModel.bodyFontSize + 'px';
                     tooltipEl.style.fontStyle = tooltipModel._bodyFontStyle;
                     tooltipEl.style.padding = tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px';
                     tooltipEl.style.pointerEvents = 'none';
                     tooltipEl.style.transition = '0.23s';
                 }
             },
                elements: {
                    line: {
                        tension: 0
                    },
                    point:{
                        radius: 0
                    }
                },
                legend: {
                  display: false
                },
                scales: {
                      yAxes: [{
                          ticks: {
                              beginAtZero: true,
                              fontSize: 16,
                              fontColor: 'rgba(0,0,0,1)',
                          },
                          gridLines: {
                            color: 'rgba(64,64,64,0.95)',
                            lineWidth: 2
                          },
                          scaleFontSize: 40
                      }],
                    xAxes: [{
                        ticks: {
                          fontSize: 16,
                          fontColor: 'rgba(0,0,0,1)',
                        },
                        gridLines: {
                          color: 'rgba(64,64,64,0.95)',
                          lineWidth: 2
                        },
                        type: 'time',
                        distribution: 'linear',
                        time: {
                            displayFormats: {
                                quarter: 'MMM YYYY'
                            }
                        }
                    }]
                },
             }
          });
        </script>

      </section>
    </div>

  </body>
</html>

Download files