admin管理员组

文章数量:1305304

I'm building an webapp where you choose airline panies and get a bar chart with scores in five categories(pany, food, luggage, punctuality, staff). I want to get a value for pany name and category, when a user clicks different parts of the chart. It's to do further things in Python using the values for pany name and category.

For example, in the image below, when a user clicks the big green bar(fourth bar from the right), I want my JS to receive pany="Air France", category="punctuality". I assume I need to do something with onclick but cannot figure out...

Context: Based on the panies you choose in the form box, a Python backend returns a json data to JS. In JS addGroupBarChart draws a chart using Chart.js and embeds it in the canvas element in html.

This is an excerpt from JavaScript

document.getElementById('button').onclick = function(){
/* returns the panies value chosen from the dropdown */
/* and draw a chart using addGroupBarChart function */
    let panies = $("#panies").val();
    let headers = new Headers()
    let init = {
        method : 'GET',
        headers : headers
    }
    let params = {
        'panies':panies
    }

    let url = getWebAppBackendUrl('/get_stats')+'/'+JSON.stringify(params)
    let promise = fetch(url, init) 
                   .then(function(response){
                       response.json()
                               .then(function(data){
                                addGroupBarChart(data.barChartGrouppany, 
                                                 data.barChartGroup.labels);
                                })
                   });
}


document.getElementById("bar-chart-group").onclick = function(......) {
/* returns the pany and category chosen from the chart */
/* this is the function I don't know how to build */
    let activePoints = // here I assume I need getPointsAtEvent(evt) but not sure...
    let pany = // pany value based on the click on the chart
    let category = // category value based on the click on the chart
    let headers = new Headers()
    let init = {
        method : 'GET',
        headers : headers
    }
    let params = {
        'pany':pany,
        'category':category
    }

    let url = getWebAppBackendUrl('/get_table')+'/'+JSON.stringify(params)
    let promise = fetch(url, init) 
                   .then(function(response) {
                       response.json()
                       .then(function(data){
                           // function to add table
                       })
                   });
}


function addGroupBarChart(data, labels) {
/* function to add a bar chart using the data returned from Python backend */
    document.getElementById('bar-card').innerHTML = '<canvas id="bar-chart-group" chart-click="onClick"></canvas>';
    i = 1
    arr = []
    data.forEach(function(d){
        pany = Object.keys(d);
        values = d[pany]['data'];
        dataset_pany = {
            label:pany,
            backgroundColor: default_colors[i],
            data:values};
        console.log("dataset_pany", dataset_pany);
        arr.push(dataset_pany);
        i+=1;
    })

    let data_grouped = {
        labels: labels,
        datasets: arr
              };

    new Chart(document.getElementById("bar-chart-group"), {
        type: "bar",
        data: data_grouped,
        options: {
          title: {
            display: false,
            text: "Sentiment by category"
          }
        }
    });
}

data and labels arguments that go into addGroupBarChart looks like

data = [{"Air France":{"data":[0.1, -0.2, 0.3, -0.1, 0.1]}}, 
        {"Lufthansa":{"data":[0.3, -0.2, 0.5, 0.2, 0.1]}}]

labels = ["pany", "food", "luggage", "punctuality", "staff"]

I tried several solutions including this one, but it made my app not show the chart even after clicking "Show chart" button. I started learning JS last week so quite noob... Any help would be appreciated. Thank you!

I'm building an webapp where you choose airline panies and get a bar chart with scores in five categories(pany, food, luggage, punctuality, staff). I want to get a value for pany name and category, when a user clicks different parts of the chart. It's to do further things in Python using the values for pany name and category.

For example, in the image below, when a user clicks the big green bar(fourth bar from the right), I want my JS to receive pany="Air France", category="punctuality". I assume I need to do something with onclick but cannot figure out...

Context: Based on the panies you choose in the form box, a Python backend returns a json data to JS. In JS addGroupBarChart draws a chart using Chart.js and embeds it in the canvas element in html.

This is an excerpt from JavaScript

document.getElementById('button').onclick = function(){
/* returns the panies value chosen from the dropdown */
/* and draw a chart using addGroupBarChart function */
    let panies = $("#panies").val();
    let headers = new Headers()
    let init = {
        method : 'GET',
        headers : headers
    }
    let params = {
        'panies':panies
    }

    let url = getWebAppBackendUrl('/get_stats')+'/'+JSON.stringify(params)
    let promise = fetch(url, init) 
                   .then(function(response){
                       response.json()
                               .then(function(data){
                                addGroupBarChart(data.barChartGroup.pany, 
                                                 data.barChartGroup.labels);
                                })
                   });
}


document.getElementById("bar-chart-group").onclick = function(......) {
/* returns the pany and category chosen from the chart */
/* this is the function I don't know how to build */
    let activePoints = // here I assume I need getPointsAtEvent(evt) but not sure...
    let pany = // pany value based on the click on the chart
    let category = // category value based on the click on the chart
    let headers = new Headers()
    let init = {
        method : 'GET',
        headers : headers
    }
    let params = {
        'pany':pany,
        'category':category
    }

    let url = getWebAppBackendUrl('/get_table')+'/'+JSON.stringify(params)
    let promise = fetch(url, init) 
                   .then(function(response) {
                       response.json()
                       .then(function(data){
                           // function to add table
                       })
                   });
}


function addGroupBarChart(data, labels) {
/* function to add a bar chart using the data returned from Python backend */
    document.getElementById('bar-card').innerHTML = '<canvas id="bar-chart-group" chart-click="onClick"></canvas>';
    i = 1
    arr = []
    data.forEach(function(d){
        pany = Object.keys(d);
        values = d[pany]['data'];
        dataset_pany = {
            label:pany,
            backgroundColor: default_colors[i],
            data:values};
        console.log("dataset_pany", dataset_pany);
        arr.push(dataset_pany);
        i+=1;
    })

    let data_grouped = {
        labels: labels,
        datasets: arr
              };

    new Chart(document.getElementById("bar-chart-group"), {
        type: "bar",
        data: data_grouped,
        options: {
          title: {
            display: false,
            text: "Sentiment by category"
          }
        }
    });
}

data and labels arguments that go into addGroupBarChart looks like

data = [{"Air France":{"data":[0.1, -0.2, 0.3, -0.1, 0.1]}}, 
        {"Lufthansa":{"data":[0.3, -0.2, 0.5, 0.2, 0.1]}}]

labels = ["pany", "food", "luggage", "punctuality", "staff"]

I tried several solutions including this one, but it made my app not show the chart even after clicking "Show chart" button. I started learning JS last week so quite noob... Any help would be appreciated. Thank you!

Share Improve this question asked May 5, 2020 at 16:10 Makoto MiyazakiMakoto Miyazaki 1,9932 gold badges29 silver badges45 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6

You can define an onClick event handler, which unfortunately is poorly documented. In your case, it would look as follows, onBarClicked being your own function that is invoked with pany and category.

options: {
  ...
  onClick: event => {
    const datasetIndex = chart.getElementAtEvent(event)[0]._datasetIndex;
    const model = chart.getElementsAtEvent(event)[datasetIndex]._model;
    onBarClicked(model.datasetLabel, model.label);
  }
}

Please have a look at your amended code below:

function onBarClicked(pany, category) {
  console.log('pany = ' + pany + ", category = " + category);
}

const default_colors = ['green', 'blue'];
function addGroupBarChart(data, labels) {
  arr = []
  data.forEach((d, i) => {
    pany = Object.keys(d)[0];
    values = d[pany]['data'];
    dataset_pany = {
      label: pany,
      backgroundColor: default_colors[i],
      data: values
    };
    arr.push(dataset_pany);
  });

  let data_grouped = {
    labels: labels,
    datasets: arr
  };

  var chart = new Chart("bar-chart-group", {
    type: "bar",
    data: data_grouped,
    options: {
      title: {
        display: false,
        text: "Sentiment by category"
      },
      onClick: event => {
        const datasetIndex = chart.getElementAtEvent(event)[0]._datasetIndex;
        const model = chart.getElementsAtEvent(event)[datasetIndex]._model;
        onBarClicked(model.datasetLabel, model.label);
      }
    }
  });
}

const data = [{"Air France":{"data":[0.1, -0.2, 0.3, -0.1, 0.1]}}, 
        {"Lufthansa":{"data":[0.3, -0.2, 0.5, 0.2, 0.1]}}];
const labels = ["pany", "food", "luggage", "punctuality", "staff"];
addGroupBarChart(data, labels);
<script src="https://cdnjs.cloudflare./ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="bar-chart-group" height="80"></canvas>

In the new version of Chart.js, the below code would work.

const ctx = $('#monitor');
monitorChart = new Chart(ctx, config);

ctx.on('click', function(evt) {
  const points = monitorChart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true);

  if (points.length) {
    const firstPoint = points[0];
    const label = monitorChart.data.labels[firstPoint.index];
    const slabel = monitorChart.data.datasets[firstPoint.datasetIndex].label;
    const value = monitorChart.data.datasets[firstPoint.datasetIndex].data[firstPoint.index];
    console.log(label, slabel, value);
  }
});

You can check Here!

the answer of @risingagain seems to be made for jquery. for vanillajs, as per the actual documentation at , the event should stay on the canvas element itself, so i'll rewrite his (otherwise working) example:

const ctx = $('#monitor');
let chart = new Chart(ctx, config);                  
chart.ctx.canvas.onclick = (evt) => {
    const points = chart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true);
                        
    if (points.length) {
        const firstPoint = points[0];
        const label = chart.data.labels[firstPoint.index];
        const slabel = chart.data.datasets[firstPoint.datasetIndex].label;
        const value = chart.data.datasets[firstPoint.datasetIndex].data[firstPoint.index];
                             
        console.log(label, slabel, value);
    }
};

本文标签: javascriptClick on interactive chartjs bar chart and get value for labels and groups in JSStack Overflow