Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create an interactive custom tooltip for chartjs

I'm using chartjs 2.8 and I've created some custom html tooltip for it, now i need to make that tooltip interactive ( aka - hoverable, clickable etc...)

The problem is that chartjs only shows the tooltip while I hover over the point of data i want to see in the tooltip, once i hover outside to get in the tooltip it disappears.

I've tried checking chartjs docs for some options solution for that but couldn't find anything helpful\working.

I've been thinking to play with my customTooltip function so it will only disappear once tooltipModel.opacity===0 and the mouse is out of the tooltip, but I'm having some difficulties here

this.tooltip = $('<div/>').addClass('chartjs-tooltip')[0];
        document.body.appendChild(this.tooltip);

        return new Chart($chart, {
            type: 'line',
            data: {
                labels: labels,
                datasets: datasets,
                cubicInterpolationMode: 'monotone'
            },
            options: Object.assign({}, options, {
                tooltips: {
                    // Disable the on-canvas tooltip
                    enabled: false,

                    custom: (tooltipModel) => {
                        // Hide if no tooltips
                        if (tooltipModel.opacity === 0) {
                            $(this.tooltip).empty().removeClass('visible');
                            return;
                        } else {
                            $(this.tooltip).addClass('visible');
                        }

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

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

                        // Set Text
                        if ( empty_datapoint ) {
                            if (tooltipModel.body) {
                                this.tooltip.innerHTML = '<table></table>';
                                let titleLines = tooltipModel.title || [];
                                let bodyLines = tooltipModel.body.map(getBody);

                                let innerHtml = '<thead>';

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

                                bodyLines.forEach(function(body, i) {
                                    let colors = tooltipModel.labelColors[i];
                                    let style = 'background:' + colors.backgroundColor + ';';
                                    let span = '<span class="color-box" style="' + style + '"></span>';
                                    innerHtml += '<tr><td>' + span + body + '</td></tr>';
                                });
                                innerHtml += '</tbody>';

                                let tableRoot = this.tooltip.querySelector('table');
                                tableRoot.innerHTML = innerHtml;
                                this.tooltip.addStyles({
                                    backgroundColor: 'rgba(0,0,0,0.8)',
                                    borderRadius: '6px',
                                    color: '#fff',
                                    fontFamily: tooltipModel._bodyFontFamily,
                                    fontSize: tooltipModel.bodyFontSize + 'px',
                                    fontStyle: tooltipModel._bodyFontStyle,
                                });
                            }
                        } else {
                            let $tooltip = this.customTooltip(tooltipModel.dataPoints);
                            $('.chartjs-tooltip').html($tooltip);
                            tooltipModel.caretX += -150;
                        }

                        // `this` will be the overall tooltip
                        let position = this.chart.$el.canvas.getBoundingClientRect();

                        // Display, position, and set styles for font
                        this.tooltip.addStyles({
                            position: 'absolute',
                            left: position.left + window.pageXOffset + tooltipModel.caretX + 'px',
                            top: position.top + window.pageYOffset + tooltipModel.caretY + 'px',
                            padding: tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px',
                            zIndex: 9999999999,
                            // pointerEvents: 'none'; // pretty sure we'll want pointer event in the future
                        });
                    }
                }
            }),
        });
like image 599
AQUANGEL Avatar asked Aug 18 '26 15:08

AQUANGEL


1 Answers

    let tooltipEl = document.getElementById('chartjs-tooltip');

    if (!tooltipEl) {
      tooltipEl = document.createElement('div');
      tooltipEl.id = 'chartjs-tooltip';
      tooltipEl.innerHTML = `<table></table>`;
      document.body.appendChild(tooltipEl);

      tooltipEl.addEventListener('mouseleave', () => {
        tooltipEl.style.opacity = 0;
      });
      tooltipEl.addEventListener('mouseenter', () => {
        tooltipEl.style.opacity = 1;
      });

You can also control tooltip visibility in afterEvent hook.

    plugins: [
      {
        id: 'turnOffTooltipPlugin',
        afterEvent(chart, args, pluginOptions) {
          const { event } = args;

          if (event.native.type === 'mouseout') {
            let tooltipEl = document.getElementById('chartjs-tooltip');

           if (tooltipEl) {
             tooltipEl.style.opacity = 0;
           }
        }
      }
     ]
like image 188
I_Shayderov Avatar answered Aug 21 '26 06:08

I_Shayderov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!