点击交互式chart.js条形图,获取JS中标签和组的值

qyzbxkaa  于 2023-10-18  发布在  Chart.js
关注(0)|答案(3)|浏览(105)

我正在开发一个网络应用程序,你可以在上面选择航空公司,然后得到一个条形图,上面有五个类别的分数(公司、食物、行李、守时、员工)。当用户单击图表的不同部分时,我想获取公司名称和类别的值。这是在Python中使用公司名称和类别的值做进一步的事情。
例如,在下图中,当用户单击大的绿色条(右起第四条)时,我希望我的JS接收company="Air France", category="punctuality"。我假设我需要对onclick做些什么,但无法弄清楚...

上下文:基于您在表单框中选择的公司,Python后端将JSON数据返回给JS。在JS中,addGroupBarChart使用Chart.js绘制图表,并将其嵌入到html中的canvas元素中。
这是从JavaScript中摘录的

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

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

document.getElementById("bar-chart-group").onclick = function(......) {
/* returns the company 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 company = // company 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 = {
        'company':company,
        '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){
        company = Object.keys(d);
        values = d[company]['data'];
        dataset_company = {
            label:company,
            backgroundColor: default_colors[i],
            data:values};
        console.log("dataset_company", dataset_company);
        arr.push(dataset_company);
        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"
          }
        }
    });
}

进入addGroupBarChartdatalabels参数如下所示

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 = ["company", "food", "luggage", "punctuality", "staff"]

我尝试了几种解决方案,包括this之一,但它使我的应用程序不显示图表,即使点击“显示图表”按钮。我上周开始学习JS,所以很noob...如果你能帮忙的话,我将不胜感激。谢谢你,谢谢!

vbopmzt1

vbopmzt11#

您可以定义一个onClick事件处理程序,不幸的是,它的文档记录得很差。在您的例子中,它看起来如下所示,onBarClicked是您自己的函数,由companycategory调用。

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

请看看下面修改后的代码:

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

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

  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 = ["company", "food", "luggage", "punctuality", "staff"];
addGroupBarChart(data, labels);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="bar-chart-group" height="80"></canvas>
llycmphe

llycmphe2#

在新版本的Chart.js中,下面的代码可以工作。

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);
  }
});

你可以在这里检查!

mctunoxg

mctunoxg3#

@risingagain的答案似乎是为jquery做的。对于vanillajs,根据实际的documentation at,事件应该留在canvas元素本身,所以我将重写他的(否则工作)示例:

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);
    }
};

相关问题