简体   繁体   中英

Chart.js / Javascript How to Override Mouseout Event Listener

I am trying to use chart.js to create a bar chart with a custom html tooltip. I would like to include some interactive stuff in the tooltip. The problem is that by default, when the mouse leaves the chart canvas, the opacity of the tooltip goes to 0. I need to override the mouseout event so that users can interact with the tooltip.

The official documentation is good, but not comprehensive... I cannot find an official answer, so I have resorted to reviewing the open source code and my developer tools.

Using Google Chrome's developer tools, I can click on the canvas and look at the event listeners tab. Under mouseout, I see the following:

canvas#chart_0.dashboard-chart.chartjs-render-monitor   chart.js 10969

removing this listener in the developer tools fixes the problem. when I click the link I can see the following code that is used to add the listener, and if I set a breakpoint I can see it being added:

...
addEventListener: function(chart, type, listener) {
        var canvas = chart.canvas;
        if (type === 'resize') {
            // Note: the resize event is not supported on all browsers.
            addResizeListener(canvas, listener, chart);
            return;
        }

        var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {});
        var proxies = expando.proxies || (expando.proxies = {});
        var proxy = proxies[chart.id + '_' + type] = function(event) {
            listener(fromNativeEvent(event, chart));
        };

        addEventListener(canvas, type, proxy);
    },
...

Hover I get chart.js from a CDN and would prefer to override this with my own javascript, rather than rolling a customized version of chart.js. I can't figure out how to remove the handler, though. I have tried the following after the chart.js script loads:

$('canvas').off('mouseout');
$('canvas#chart_0').off('mouseout');
$('canvas#chart_0.dashboard-chart.chartjs-render-monitor').off('mouseout');
$('#chart_0').off('mouseout');
$('.chartjs-render-monitor').off('mouseout');

None of these selectors remove the event listener. I have also tried something to the effect of $('canvas#chart_0')[0].removeEventListener('mouseout') but this requires the listener as a parameter, and I'm not sure how to get a reference to that since it is passed anonymously. Can anyone recommend a way of getting rid of the default event listener, or a way to pass a configuration option to chart.js to override the default behavior? Thanks in advance.

For the following example I have used the sample provided on the custom tooltip documentation that are available here .

The object that is passed to the custom function, in this case tooltipModel , have a propriety that will be set to 0 when the cursor leaves the hovered item, if we ignore the line that hides the tooltip it will stay visible until you hovered another item.

So the lines that have to be changed are the following:

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

A full working example:

 var ctx = document.getElementById('bar-chart').getContext('2d'); var chart = new Chart(ctx, { type: 'line', data: { labels: ['A', ' B', ' C'], datasets: [{ label: "Y", data: [5, 2, 0] }, { label: "Z", data: [7, 0, 3] } ] }, options: { tooltips: { enabled: 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></table>'; document.body.appendChild(tooltipEl); } // Hide if no tooltip if (tooltipModel.opacity === 0) { // remove the next line //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'; } } } });
 #chartjs-tooltip { opacity: 1; position: absolute; background: rgba(0, 0, 0, .7); color: white; border-radius: 3px; -webkit-transition: all .1s ease; transition: all .1s ease; pointer-events: none; -webkit-transform: translate(-50%, 0); transform: translate(-50%, 0); }
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script> <canvas id="bar-chart" width="400" height="200"></canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM