Charts.js v2:始终在图表上显示自定义(html)工具提示

时间:2017-06-20 10:09:35

标签: charts chart.js chart.js2

我的目标是创建自定义工具提示,并始终显示它们。稍后会有一些更奇特的东西,但是现在我正在努力实现这两件事。

要创建自定义工具提示,请使用charts.js docs的教程;在stackoverflow上我找到了solution for always showing the tooltips

所以现在我有两个工具提示:标准工具提示,显示在绘制后并保持可见状态,以及自定义工具提示,它们目前正在工作但只出现在悬停点/数据点上。

jsFiddle https://jsfiddle.net/2c4261wj/1/以下图片显示问题。红色容器显示自定义工具提示,仅在悬停点时出现。

enter image description here

而不是标准的工具提示,我想在AfterDraw之后总是显示自定义的工具提示,但我无法做到这一点。

原始码位

工具提示选项中的自定义工具提示:

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) {
    tooltipEl.style.opacity = 1;
    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 = '<div>';
    titleLines.forEach(function(title) {
        innerHtml += '<span>' + title + '</span>';
    });
    innerHtml += '</div>';
    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 class="chartjs-tooltip-key" style="' + style + '"></span>';
        innerHtml += '<div class="inner">' + span + body + '</div>';
    });
    innerHtml += 'last';
    var tableRoot = tooltipEl;
    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.left = position.left + tooltipModel.caretX - 100 + 'px';
tooltipEl.style.top = position.top + tooltipModel.caretY - 100 + 'px';
tooltipEl.style.fontFamily = tooltipModel._fontFamily;
tooltipEl.style.fontSize = tooltipModel.fontSize;
tooltipEl.style.fontStyle = tooltipModel._fontStyle;
tooltipEl.style.padding = tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px';
}

始终显示工具提示:

Chart.pluginService.register({
        beforeRender: function (chart) {
            if (chart.config.options.showAllTooltips) {
                // create an array of tooltips
                // we can't use the chart tooltip because there is only one tooltip per chart
                chart.pluginTooltips = [];
                chart.config.data.datasets.forEach(function (dataset, i) {
                    chart.getDatasetMeta(i).data.forEach(function (sector, j) {
                        chart.pluginTooltips.push(new Chart.Tooltip({
                            _chart: chart.chart,
                            _chartInstance: chart,
                            _data: chart.data,
                            _options: chart.options.tooltips,
                            _active: [sector]
                        }, chart));
                    });
                });

                // turn off normal tooltips
                chart.options.tooltips.enabled = false;
            }
        },
        afterDraw: function (chart, easing) {
            if (chart.config.options.showAllTooltips) {
                // we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
                if (!chart.allTooltipsOnce) {
                    if (easing !== 1)
                        return;
                    chart.allTooltipsOnce = true;
                }

                // turn on tooltips
                chart.options.tooltips.enabled = true;
                Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
                    tooltip.initialize();
                    tooltip.update();
                    // we don't actually need this since we are not animating tooltips
                    tooltip.pivot();
                    tooltip.transition(easing).draw();
                });
                chart.options.tooltips.enabled = false;
            }
        }
    });

我试图在第一个插件中使用自定义工具提示,但没有结果,也许我在插件中引用了错误。 有什么想法吗?

1 个答案:

答案 0 :(得分:1)

所以,我找到了解决方案。之前,我尝试使用自定义工具提示并创建了一个插件,这样可以使自定义工具提示在加载时显示并保持可见。

我现在做的是:

  • 删除自定义工具提示
  • 创建一个新插件来处理我对颜色的所有需求和愿望

首先:working fiddle of the current state

实际上它非常简单;插件获取所有数据集,循环遍历它们并在画布上绘制内容。感谢插件,您可以通过将其保存到数组来访问所有数据,然后是...抓住它们并做任何你想做的事。

魔法发生在这里:

Chart.plugins.register({
afterDraw: function(chart, easing) {
    // To only draw at the end of animation, check for easing === 1
    var debug = false;
    var ctx = chart.chart.ctx;
    var numbers = [],
        position = [],
        dataString = [],
        safetyCounter = 0;
    var datasetAmount = chart.data.datasets.length;
    var datasetLength = chart.getDatasetMeta(0).data.length;
    var amountLength = (datasetAmount * datasetLength);
    chart.data.datasets.forEach(function(dataset, i) {
        var meta = chart.getDatasetMeta(i);
        if (!meta.hidden) {
            meta.data.forEach(function(element, index) {
                if (numbers.indexOf(dataset.data[index]) < 0) {
                    numbers.push(dataset.data[index]);
                }
                position.push(element.tooltipPosition());
                var fontSize = 20;
                var fontStyle = 'bold';
                var fontFamily = 'Helvetica Neue';
                ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.lineWidth = 2;
                dataString.push(dataset.data[index].toString() + '%');
                var padding = 5;
                if (numbers.length === amountLength) {
                    if (safetyCounter === 0) {
                        safetyCounter++
                    }
                    for (var k = 0; k < numbers.length; k++) {
                        if (k < datasetLength) {
                            ctx.strokeStyle = "#c7d85e";
                            ctx.fillStyle = "#c7d85e";
                            if (numbers[k] >= numbers[k + datasetLength]) {
                                ctx.beginPath();
                                ctx.moveTo(position[k].x, position[k].y - 50);
                                ctx.lineTo(position[k].x, position[k].y);
                                ctx.stroke();
                                ctx.fillText(dataString[k], position[k].x, position[k].y - 50 - (fontSize / 2) - padding);
                            } else {
                                ctx.beginPath();
                                ctx.moveTo(position[k].x, position[k].y + 50);
                                ctx.lineTo(position[k].x, position[k].y);
                                ctx.stroke();
                                ctx.fillText(dataString[k], position[k].x, position[k].y + 80 - (fontSize / 2) - padding);
                            }
                        } else {
                            ctx.strokeStyle = "#4f708b";
                            ctx.fillStyle = "#4f708b";
                            if (numbers[k] >= numbers[k - datasetLength]) {
                                ctx.beginPath();
                                ctx.moveTo(position[k].x, position[k].y - 50);
                                ctx.lineTo(position[k].x, position[k].y);
                                ctx.stroke();
                                ctx.fillText(dataString[k], position[k].x, position[k].y - 50 - (fontSize / 2) - padding);
                            } else {
                                ctx.beginPath();
                                ctx.moveTo(position[k].x, position[k].y + 50);
                                ctx.lineTo(position[k].x, position[k].y);
                                ctx.stroke();
                                ctx.fillText(dataString[k], position[k].x, position[k].y + 80 - (fontSize / 2) - padding);
                            }
                        }
                    }
                } else {
                    // nothing yet here
                }
            });
        }
    });
    si++;
    // necessary for prevent standard tooltips from showing
    // but I also use css pointer events for preventing canvas to respond to mouseevents
    if (chart.config.options.showAllTooltips) {
        if (!chart.allTooltipsOnce) {
            if (easing !== 1) return;
            chart.allTooltipsOnce = true;
        }
        chart.options.tooltips.enabled = true;
        Chart.helpers.each(chart.pluginTooltips, function(tooltip) {
            tooltip.initialize();
            tooltip.update();
            tooltip.pivot();
            tooltip.transition(easing).draw();
        });
        chart.options.tooltips.enabled = false;
    }
}
});