使Chart.js雷达标签可点击

时间:2018-05-22 14:56:28

标签: javascript charts chart.js

是否有人设法使Chart.js Radar周边的标签可以点击?

似乎并不是一个明显的解决方案。

enter image description here

2 个答案:

答案 0 :(得分:1)

我通过将RadialLinear标度的标签位置计算复制到事件处理程序中,为2.8.0版提出了解决方案。

document.getElementById("myChart").onclick = function (e) {
    var helpers = Chart.helpers;
    var scale = myRadarChart.scale;
    var opts = scale.options;
    var tickOpts = opts.ticks;

    // Position of click relative to canvas.
    var mouseX = e.offsetX;
    var mouseY = e.offsetY;

    var labelPadding = 5; // number pixels to expand label bounding box by

    // get the label render position
    // calcs taken from drawPointLabels() in scale.radialLinear.js
    var tickBackdropHeight = (tickOpts.display && opts.display) ?
        helpers.valueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize)
        + 5: 0;
    var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
    for (var i = 0; i < scale.pointLabels.length; i++) {
        // Extra spacing for top value due to axis labels
        var extra = (i === 0 ? tickBackdropHeight / 2 : 0);
        var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5);

        // get label size info.
        // TODO fix width=0 calc in Brave?
        // https://github.com/brave/brave-browser/issues/1738
        var plSize = scale._pointLabelSizes[i];

        // get label textAlign info
        var angleRadians = scale.getIndexAngle(i);
        var angle = helpers.toDegrees(angleRadians);
        var textAlign = 'right';
        if (angle == 0 || angle == 180) {
            textAlign = 'center';
        } else if (angle < 180) {
            textAlign = 'left';
        }

        // get label vertical offset info
        // also from drawPointLabels() calcs
        var verticalTextOffset = 0;
        if (angle === 90 || angle === 270) {
            verticalTextOffset = plSize.h / 2;
        } else if (angle > 270 || angle < 90) {
            verticalTextOffset = plSize.h;
        }

        // Calculate bounding box based on textAlign
        var labelTop = pointLabelPosition.y - verticalTextOffset - labelPadding;
        var labelHeight = 2*labelPadding + plSize.h;
        var labelBottom = labelTop + labelHeight;

        var labelWidth = plSize.w + 2*labelPadding;
        var labelLeft;
        switch (textAlign) {
        case 'center':
          var labelLeft = pointLabelPosition.x - labelWidth/2;
          break;
        case 'left':
          var labelLeft = pointLabelPosition.x - labelPadding;

          break;
        case 'right':
          var labelLeft = pointLabelPosition.x - labelWidth + labelPadding;
          break;
        default:
          console.log('ERROR: unknown textAlign '+textAlign);
        }
        var labelRight = labelLeft + labelWidth;

        // Render a rectangle for testing purposes
        ctx.save();
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 1;
        ctx.strokeRect(labelLeft, labelTop, labelWidth, labelHeight);
        ctx.restore();

        // compare to the current click
        if (mouseX >= labelLeft && mouseX <= labelRight && mouseY <= labelBottom && mouseY >= labelTop) {
            alert(scale.pointLabels[i]+' clicked');
            // Break loop to prevent multiple clicks, if they overlap we take the first one.
            break;
        }
    }
};

JSFiddle在这里:

https://jsfiddle.net/simoncoggins/7r08uLk9/

该方法的缺点是,如果将来核心标签实现发生更改,它将无法使用。如果库将标签位置的计算与其呈现分离,并开始通过API公开位置信息,将会更好。然后,可以大大简化此解决方案,并且对库更改更健壮。

我已经打开了一张票证,可以在此处进行更改:

https://github.com/chartjs/Chart.js/issues/6549

如果对您有用,请对此问题发表评论。

答案 1 :(得分:0)

感谢Pogrindis。这里的答案适用于Chart.js v2.1:Chart.js click on labels, using bar chart

要使Chart.js v5.0 +工作,请将以下函数添加回Chart.js代码。

  

LinearRadialScale = Chart.LinearScaleBase.extend({...})

getValueCount: function() {
        return this.chart.data.labels.length;
    }