dnmh
dnmh

Reputation: 2135

Chart.js turn labels into links

I'm not sure this is possible without doing something along the line of: Create links in HTML canvas but let's make sure.

Is there a way to (relatively) simply turn Chart.js labels into links? The chart in question is the radar chart: http://www.chartjs.org/docs/#radar-chart (So far I've been using the legend for that, works fine with a little library modification, but now I should use the labels themselves.)

Upvotes: 9

Views: 5822

Answers (2)

joeljpa
joeljpa

Reputation: 539

It's really late but bencekd's answer to "Add Link to X-Label Chart.js" worked for me.

My project uses the old Chart.js v1 and it's for a bar chart, not radar. You'll have to modify it accordingly as per the current version Chart.js. I don't see why it shouldn't work for a radar with a little refactoring.

Code (their provided Fiddle, one minor change by me, comments by "/*" indicate my lines):

var randomScalingFactor = function() {
    return Math.round(Math.random()*100)
};

var barChartData = {
    labels :
    ["January","February","March","April","May","June","July"],
    datasets : [
        {
            fillColor : "rgba(220,220,220,0.5)",
            strokeColor : "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
        },
        {
            fillColor : "rgba(151,187,205,0.5)",
            strokeColor : "rgba(151,187,205,0.8)",
            highlightFill : "rgba(151,187,205,0.75)",
            highlightStroke : "rgba(151,187,205,1)",
            data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
        }
    ]

}

var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx).Bar(barChartData, {
    responsive : true
});

$("#canvas").click(
    function(evt){
        var ctx = document.getElementById("canvas").getContext("2d");
        // from the endPoint we get the end of the bars area
        var base = myBar.scale.endPoint;
        var height = myBar.chart.height;
        var width = myBar.chart.width;
        // only call if event is under the xAxis
        if(evt.pageY > base){
            // how many xLabels we have
            var count = myBar.scale.valuesCount;
            var padding_left = myBar.scale.xScalePaddingLeft;
            var padding_right = myBar.scale.xScalePaddingRight;
            // calculate width for each label
            var xwidth = (width-padding_left-padding_right)/count;
            // determine what label were clicked on AND PUT IT INTO bar_index
            var bar_index = (evt.offsetX - padding_left) / xwidth;
            // don't call for padding areas
            if(bar_index > 0 & bar_index < count){
                bar_index = parseInt(bar_index);
                // either get label from barChartData
                //console.log("barChartData:" + barChartData.labels[bar_index]);
                // or from current data
                /* barChartData didn't work for me, so disabled above */
                var ret = [];
                for (var i = 0; i < myBar.datasets[0].bars.length; i++) {
                    ret.push(myBar.datasets[0].bars[i].label)
                };
                console.log("current data:" + ret[bar_index]);
                // based on the label you can call any function
                /* I made to go where I wanted here with a window.location.href
           and taking the label (ret[bar_index]) as an argument */
            }
        }
    }
);  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
    <div style="width: 50%">
            <canvas id="canvas" height="450" width="600"></canvas>
        </div>
    <div>
    Click on the x labels!
    </div>
    <div id="hello">
    </div>

Upvotes: 0

LeeLenalee
LeeLenalee

Reputation: 31371

You can listen to the click event and then loop through all the pointLabels check if the click is in that box. If this is the case you get the corresponding label from the array containing all the labels.

Then you can open use window.location = link or window.open(link) to go to your link.

Example that searches the color on google on click:

const options = {
  type: 'radar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'orange'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'pink'
      }
    ]
  },
  options: {
    onClick: (evt, activeEls, chart) => {
      const {
        x,
        y
      } = evt;
      let index = -1;

      for (let i = 0; i < chart.scales.r._pointLabelItems.length; i++) {
        const {
          bottom,
          top,
          left,
          right
        } = chart.scales.r._pointLabelItems[i];

        if (x >= left && x <= right && y >= top && y <= bottom) {
          index = i;
          break;
        }
      }

      if (index === -1) {
        return;
      }

      const clickedLabel = chart.scales.r._pointLabels[index];

      window.open(`https://www.google.com/search?q=color%20${clickedLabel}`); // Blocked in stack snipet. See fiddle
      console.log(clickedLabel)
    }
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>

Fiddle: https://jsfiddle.net/Leelenaleee/fnqr4c7j/22/

Upvotes: 1

Related Questions