2020 年 10 月 1 日,星期四
作者:Sandy Galloway

Highcharts 集成

最近,我们收到了一些反馈,询问如何以图形格式显示来自 DataTable 的信息。使用我们的 API 和图表库,这是完全可以做到的。有很多可用的库,但在本博文中,我们将使用非常流行的 Highcharts,展示如何将其集成到您的 DataTables 项目中。

这是一个我们将创建的集成类型的示例。请注意,当我们过滤表格时,图表会重新绘制以反映过滤后的数据。

姓名职位办公室薪水
Tiger Nixon系统架构师爱丁堡$320,800
Garrett Winters会计东京$170,750
Ashton Cox初级技术作者旧金山$86,000
Cedric Kelly高级 JavaScript 开发者爱丁堡$433,060
Airi Satou会计东京$162,700
Brielle Williamson集成专家纽约$372,000
Herrod Chandler销售助理旧金山$137,500
Rhona Davidson集成专家东京$327,900
Colleen HurstJavaScript 开发者旧金山$205,500
Sonya Frost软件工程师爱丁堡$103,600
Jena Gaines办公室经理伦敦$90,560
Quinn Flynn支持主管爱丁堡$342,000
Charde Marshall区域主管旧金山$470,600
Haley Kennedy高级营销设计师伦敦$313,500
Tatyana Fitzpatrick区域主管伦敦$385,750
Michael Silva营销设计师伦敦$198,500
Paul Byrd首席财务官 (CFO)纽约$725,000
Gloria Little系统管理员纽约$237,500
Bradley Greer软件工程师伦敦$132,000
Dai Rios人事主管爱丁堡$217,500
Jenette Caldwell开发主管纽约$345,000
Yuri Berry首席营销官 (CMO)纽约$675,000
Caesar Vance售前支持纽约$106,450
Doris Wilder销售助理悉尼$85,600
Angelica Ramos首席执行官 (CEO)伦敦$1,200,000
Gavin Joyce开发者爱丁堡$92,575
Jennifer Chang区域主管新加坡$357,650
Brenden Wagner软件工程师旧金山$206,850
Fiona Green首席运营官 (COO)旧金山$850,000
Shou Itou区域营销东京$163,000
Michelle House集成专家悉尼$95,400
Suki Burks开发者伦敦$114,500
Prescott Bartlett技术作者伦敦$145,000
Gavin Cortez团队主管旧金山$235,500
Martena Mccray售后支持爱丁堡$324,050
Unity Butler营销设计师旧金山$85,675
Howard Hatfield办公室经理旧金山$164,500
Hope Fuentes秘书旧金山$109,850
Vivian Harrell财务总监旧金山$452,500
Timothy Mooney办公室经理伦敦$136,200
Jackson Bradshaw总监纽约$645,750
Olivia Liang支持工程师新加坡$234,500
Bruno Nash软件工程师伦敦$163,500
Sakura Yamamoto支持工程师东京$139,575
Thor Walton开发者纽约$98,540
Finn Camacho支持工程师旧金山$87,500
Serge Baldwin数据协调员新加坡$138,575
Zenaida Frank软件工程师纽约$125,250
Zorita Serrano软件工程师旧金山$115,000
Jennifer Acosta初级 JavaScript 开发者爱丁堡$75,650
Cara Stevens销售助理纽约$145,600
Hermione Butler区域主管伦敦$356,250
Lael Greer系统管理员伦敦$103,500
Jonas Alexander开发者旧金山$86,500
Shad Decker区域主管爱丁堡$183,000
Michael BruceJavaScript 开发者新加坡$183,000
Donna Snider客户支持纽约$112,000

在这篇文章中,我将逐步介绍将 DataTables 与 Highcharts 链接起来的过程。我将涵盖

  • 静态图表
  • 异步图表
  • 带数据处理的图表

静态图表

Highcharts 提供了多种不同的图表类型。在本博文中,我将使用饼图和柱状图。

下面显示了一个非常基本的饼图初始化

var myChart = Highcharts.chart('container', {
    chart: {
        type: 'pie',
    },
    title: {
        text: 'Staff Count Per Office',
    },
    series: [
        {
            data: countMap,
        },
    ],
});

配置相当直白。我们将 chart.type 设置为 pie,用于饼图,并将 title.text 设置为 每个办公室的员工数量series 数组被设置为包含一个对象,该对象包含该系列所需的数据。

现在,剩下的就是从 DataTable 收集数据。为此,我们只需使用 column().data() 方法迭代所需列的值,在迭代过程中递增值。然后,将生成的箱体数据转换为 Highcharts 可以使用的对象数组。

var table = $('#example').DataTable();
var counts = {};

// Count the number of entries for each office
table
    .column(2, { search: 'applied' })
    .data()
    .each(function (val) {
        if (counts[val]) {
            counts[val] += 1;
        } else {
            counts[val] = 1;
        }
    });

// And map it to the format highcharts uses
var countMap = $.map(counts, function (val, key) {
    return {
        name: key,
        y: val,
    };
});

该代码生成的表格和图表的示例如下所示。另外,还提供了一个 可用的在线版本,您可以对其进行修改和实验。

姓名职位办公室薪水
Tiger Nixon系统架构师爱丁堡$320,800
Garrett Winters会计东京$170,750
Ashton Cox初级技术作者旧金山$86,000
Cedric Kelly高级 JavaScript 开发者爱丁堡$433,060
Airi Satou会计东京$162,700
Brielle Williamson集成专家纽约$372,000
Herrod Chandler销售助理旧金山$137,500
Rhona Davidson集成专家东京$327,900
Colleen HurstJavaScript 开发者旧金山$205,500
Sonya Frost软件工程师爱丁堡$103,600
Jena Gaines办公室经理伦敦$90,560
Quinn Flynn支持主管爱丁堡$342,000
Charde Marshall区域主管旧金山$470,600
Haley Kennedy高级营销设计师伦敦$313,500
Tatyana Fitzpatrick区域主管伦敦$385,750
Michael Silva营销设计师伦敦$198,500
Paul Byrd首席财务官 (CFO)纽约$725,000
Gloria Little系统管理员纽约$237,500
Bradley Greer软件工程师伦敦$132,000
Dai Rios人事主管爱丁堡$217,500
Jenette Caldwell开发主管纽约$345,000
Yuri Berry首席营销官 (CMO)纽约$675,000
Caesar Vance售前支持纽约$106,450
Doris Wilder销售助理悉尼$85,600
Angelica Ramos首席执行官 (CEO)伦敦$1,200,000
Gavin Joyce开发者爱丁堡$92,575
Jennifer Chang区域主管新加坡$357,650
Brenden Wagner软件工程师旧金山$206,850
Fiona Green首席运营官 (COO)旧金山$850,000
Shou Itou区域营销东京$163,000
Michelle House集成专家悉尼$95,400
Suki Burks开发者伦敦$114,500
Prescott Bartlett技术作者伦敦$145,000
Gavin Cortez团队主管旧金山$235,500
Martena Mccray售后支持爱丁堡$324,050
Unity Butler营销设计师旧金山$85,675
Howard Hatfield办公室经理旧金山$164,500
Hope Fuentes秘书旧金山$109,850
Vivian Harrell财务总监旧金山$452,500
Timothy Mooney办公室经理伦敦$136,200
Jackson Bradshaw总监纽约$645,750
Olivia Liang支持工程师新加坡$234,500
Bruno Nash软件工程师伦敦$163,500
Sakura Yamamoto支持工程师东京$139,575
Thor Walton开发者纽约$98,540
Finn Camacho支持工程师旧金山$87,500
Serge Baldwin数据协调员新加坡$138,575
Zenaida Frank软件工程师纽约$125,250
Zorita Serrano软件工程师旧金山$115,000
Jennifer Acosta初级 JavaScript 开发者爱丁堡$75,650
Cara Stevens销售助理纽约$145,600
Hermione Butler区域主管伦敦$356,250
Lael Greer系统管理员伦敦$103,500
Jonas Alexander开发者旧金山$86,500
Shad Decker区域主管爱丁堡$183,000
Michael BruceJavaScript 开发者新加坡$183,000
Donna Snider客户支持纽约$112,000

现在这很酷,但如果图表可以反映应用于它的任何过滤效果,岂不是更好?继续阅读...

异步图表

要实现这一点,我们必须对上面的代码进行一些修改。我们将把办公室计数从 $(document).ready(...) 监听器中移出,并将其放入自己的函数中,并用对我们新函数的调用替换它。该函数应类似于以下内容

function chartData(table) {
    var counts = {};

    // Count the number of entries for each office
    table
        .column(2, { search: 'applied' })
        .data()
        .each(function (val) {
            if (counts[val]) {
                counts[val] += 1;
            } else {
                counts[val] = 1;
            }
        });

    // And map it to the format highcharts uses
    return $.map(counts, function (val, key) {
        return {
            name: key,
            y: val,
        };
    });
}

使用这种方法意味着,随着过滤的进行,职位会从图表中消失,从而带来更简洁的图表体验。

现在,剩下的就是添加一个监听器,用于在过滤发生时告诉图表使用新数据更新 - 为此,我们使用 draw

table.on('draw', function () {
    // Set the data for the first series to be the map returned from the chartData function
    myChart.series[0].setData(chartData(table));
});

下面给出了此代码的示例,和以前一样,提供了展示完整运行代码的在线版本

姓名职位办公室薪水
Tiger Nixon系统架构师爱丁堡$320,800
Garrett Winters会计东京$170,750
Ashton Cox初级技术作者旧金山$86,000
Cedric Kelly高级 JavaScript 开发者爱丁堡$433,060
Airi Satou会计东京$162,700
Brielle Williamson集成专家纽约$372,000
Herrod Chandler销售助理旧金山$137,500
Rhona Davidson集成专家东京$327,900
Colleen HurstJavaScript 开发者旧金山$205,500
Sonya Frost软件工程师爱丁堡$103,600
Jena Gaines办公室经理伦敦$90,560
Quinn Flynn支持主管爱丁堡$342,000
Charde Marshall区域主管旧金山$470,600
Haley Kennedy高级营销设计师伦敦$313,500
Tatyana Fitzpatrick区域主管伦敦$385,750
Michael Silva营销设计师伦敦$198,500
Paul Byrd首席财务官 (CFO)纽约$725,000
Gloria Little系统管理员纽约$237,500
Bradley Greer软件工程师伦敦$132,000
Dai Rios人事主管爱丁堡$217,500
Jenette Caldwell开发主管纽约$345,000
Yuri Berry首席营销官 (CMO)纽约$675,000
Caesar Vance售前支持纽约$106,450
Doris Wilder销售助理悉尼$85,600
Angelica Ramos首席执行官 (CEO)伦敦$1,200,000
Gavin Joyce开发者爱丁堡$92,575
Jennifer Chang区域主管新加坡$357,650
Brenden Wagner软件工程师旧金山$206,850
Fiona Green首席运营官 (COO)旧金山$850,000
Shou Itou区域营销东京$163,000
Michelle House集成专家悉尼$95,400
Suki Burks开发者伦敦$114,500
Prescott Bartlett技术作者伦敦$145,000
Gavin Cortez团队主管旧金山$235,500
Martena Mccray售后支持爱丁堡$324,050
Unity Butler营销设计师旧金山$85,675
Howard Hatfield办公室经理旧金山$164,500
Hope Fuentes秘书旧金山$109,850
Vivian Harrell财务总监旧金山$452,500
Timothy Mooney办公室经理伦敦$136,200
Jackson Bradshaw总监纽约$645,750
Olivia Liang支持工程师新加坡$234,500
Bruno Nash软件工程师伦敦$163,500
Sakura Yamamoto支持工程师东京$139,575
Thor Walton开发者纽约$98,540
Finn Camacho支持工程师旧金山$87,500
Serge Baldwin数据协调员新加坡$138,575
Zenaida Frank软件工程师纽约$125,250
Zorita Serrano软件工程师旧金山$115,000
Jennifer Acosta初级 JavaScript 开发者爱丁堡$75,650
Cara Stevens销售助理纽约$145,600
Hermione Butler区域主管伦敦$356,250
Lael Greer系统管理员伦敦$103,500
Jonas Alexander开发者旧金山$86,500
Shad Decker区域主管爱丁堡$183,000
Michael BruceJavaScript 开发者新加坡$183,000
Donna Snider客户支持纽约$112,000

这不仅适用于 DataTables 的全局过滤器输入,也适用于 SearchPanes 等扩展,您可以在以下示例中看到。这里的一个细微差别是,我们正在绘制 职位 列。同样,我已经链接了一个 在线版本

姓名职位办公室薪水
Tiger Nixon系统架构师爱丁堡$320,800
Garrett Winters会计东京$170,750
Ashton Cox初级技术作者旧金山$86,000
Cedric Kelly高级 JavaScript 开发者爱丁堡$433,060
Airi Satou会计东京$162,700
Brielle Williamson集成专家纽约$372,000
Herrod Chandler销售助理旧金山$137,500
Rhona Davidson集成专家东京$327,900
Colleen HurstJavaScript 开发者旧金山$205,500
Sonya Frost软件工程师爱丁堡$103,600
Jena Gaines办公室经理伦敦$90,560
Quinn Flynn支持主管爱丁堡$342,000
Charde Marshall区域主管旧金山$470,600
Haley Kennedy高级营销设计师伦敦$313,500
Tatyana Fitzpatrick区域主管伦敦$385,750
Michael Silva营销设计师伦敦$198,500
Paul Byrd首席财务官 (CFO)纽约$725,000
Gloria Little系统管理员纽约$237,500
Bradley Greer软件工程师伦敦$132,000
Dai Rios人事主管爱丁堡$217,500
Jenette Caldwell开发主管纽约$345,000
Yuri Berry首席营销官 (CMO)纽约$675,000
Caesar Vance售前支持纽约$106,450
Doris Wilder销售助理悉尼$85,600
Angelica Ramos首席执行官 (CEO)伦敦$1,200,000
Gavin Joyce开发者爱丁堡$92,575
Jennifer Chang区域主管新加坡$357,650
Brenden Wagner软件工程师旧金山$206,850
Fiona Green首席运营官 (COO)旧金山$850,000
Shou Itou区域营销东京$163,000
Michelle House集成专家悉尼$95,400
Suki Burks开发者伦敦$114,500
Prescott Bartlett技术作者伦敦$145,000
Gavin Cortez团队主管旧金山$235,500
Martena Mccray售后支持爱丁堡$324,050
Unity Butler营销设计师旧金山$85,675
Howard Hatfield办公室经理旧金山$164,500
Hope Fuentes秘书旧金山$109,850
Vivian Harrell财务总监旧金山$452,500
Timothy Mooney办公室经理伦敦$136,200
Jackson Bradshaw总监纽约$645,750
Olivia Liang支持工程师新加坡$234,500
Bruno Nash软件工程师伦敦$163,500
Sakura Yamamoto支持工程师东京$139,575
Thor Walton开发者纽约$98,540
Finn Camacho支持工程师旧金山$87,500
Serge Baldwin数据协调员新加坡$138,575
Zenaida Frank软件工程师纽约$125,250
Zorita Serrano软件工程师旧金山$115,000
Jennifer Acosta初级 JavaScript 开发者爱丁堡$75,650
Cara Stevens销售助理纽约$145,600
Hermione Butler区域主管伦敦$356,250
Lael Greer系统管理员伦敦$103,500
Jonas Alexander开发者旧金山$86,500
Shad Decker区域主管爱丁堡$183,000
Michael BruceJavaScript 开发者新加坡$183,000
Donna Snider客户支持纽约$112,000

带数据处理的图表

当然,也可以对来自 DataTable 的数据进行更多处理。下面的示例创建了一个柱状图,显示了示例表格中员工的平均薪水,按办公室分类。当然,这里还有一个链接,指向 在线版本

姓名职位办公室薪水
Tiger Nixon系统架构师爱丁堡$320,800
Garrett Winters会计东京$170,750
Ashton Cox初级技术作者旧金山$86,000
Cedric Kelly高级 JavaScript 开发者爱丁堡$433,060
Airi Satou会计东京$162,700
Brielle Williamson集成专家纽约$372,000
Herrod Chandler销售助理旧金山$137,500
Rhona Davidson集成专家东京$327,900
Colleen HurstJavaScript 开发者旧金山$205,500
Sonya Frost软件工程师爱丁堡$103,600
Jena Gaines办公室经理伦敦$90,560
Quinn Flynn支持主管爱丁堡$342,000
Charde Marshall区域主管旧金山$470,600
Haley Kennedy高级营销设计师伦敦$313,500
Tatyana Fitzpatrick区域主管伦敦$385,750
Michael Silva营销设计师伦敦$198,500
Paul Byrd首席财务官 (CFO)纽约$725,000
Gloria Little系统管理员纽约$237,500
Bradley Greer软件工程师伦敦$132,000
Dai Rios人事主管爱丁堡$217,500
Jenette Caldwell开发主管纽约$345,000
Yuri Berry首席营销官 (CMO)纽约$675,000
Caesar Vance售前支持纽约$106,450
Doris Wilder销售助理悉尼$85,600
Angelica Ramos首席执行官 (CEO)伦敦$1,200,000
Gavin Joyce开发者爱丁堡$92,575
Jennifer Chang区域主管新加坡$357,650
Brenden Wagner软件工程师旧金山$206,850
Fiona Green首席运营官 (COO)旧金山$850,000
Shou Itou区域营销东京$163,000
Michelle House集成专家悉尼$95,400
Suki Burks开发者伦敦$114,500
Prescott Bartlett技术作者伦敦$145,000
Gavin Cortez团队主管旧金山$235,500
Martena Mccray售后支持爱丁堡$324,050
Unity Butler营销设计师旧金山$85,675
Howard Hatfield办公室经理旧金山$164,500
Hope Fuentes秘书旧金山$109,850
Vivian Harrell财务总监旧金山$452,500
Timothy Mooney办公室经理伦敦$136,200
Jackson Bradshaw总监纽约$645,750
Olivia Liang支持工程师新加坡$234,500
Bruno Nash软件工程师伦敦$163,500
Sakura Yamamoto支持工程师东京$139,575
Thor Walton开发者纽约$98,540
Finn Camacho支持工程师旧金山$87,500
Serge Baldwin数据协调员新加坡$138,575
Zenaida Frank软件工程师纽约$125,250
Zorita Serrano软件工程师旧金山$115,000
Jennifer Acosta初级 JavaScript 开发者爱丁堡$75,650
Cara Stevens销售助理纽约$145,600
Hermione Butler区域主管伦敦$356,250
Lael Greer系统管理员伦敦$103,500
Jonas Alexander开发者旧金山$86,500
Shad Decker区域主管爱丁堡$183,000
Michael BruceJavaScript 开发者新加坡$183,000
Donna Snider客户支持纽约$112,000

此示例的代码与前面的示例非常相似,只是对我们创建的额外函数进行了一些调整。

function getSalaries(table) {
    var salaryCounts = {};
    var salary = {};

    // Get the row indexes for the rows displayed under the current search
    var indexes = table.rows({ search: 'applied' }).indexes().toArray();

    // For each row, extract the office and add the salary to the array
    for (var i = 0; i < indexes.length; i++) {
        var office = table.cell(indexes[i], 2).data();
        if (salaryCounts[office] === undefined) {
            salaryCounts[office] = [
                +table
                    .cell(indexes[i], 3)
                    .data()
                    .replace(/[^0-9.]/g, ''),
            ];
        } else {
            salaryCounts[office].push(
                +table
                    .cell(indexes[i], 3)
                    .data()
                    .replace(/[^0-9.]/g, '')
            );
        }
    }

    // Extract the office names that are present in the table
    var keys = Object.keys(salaryCounts);

    // For each office work out the average salary
    for (var i = 0; i < keys.length; i++) {
        var length = salaryCounts[keys[i]].length;
        var total = salaryCounts[keys[i]].reduce((a, b) => a + b, 0);
        salary[keys[i]] = total / length;
    }

    return salary;
}

这里我们有两个对象,第一个 salary 对象将保存我们用于柱状图的最终数据,而 salaryCounts 是一个临时对象,它将允许我们执行一些额外的处理。

我们还必须对 series 变量进行更改,数据现在是 salary 数组的值。我们还需要声明一个 x 轴和一个 y 轴。将所有这些放在一起,我们就得到了以下脚本,该脚本用于上面的示例。

$(document).ready(function () {
    var table = $('#example').DataTable();
    var salary = getSalaries(table);

    // Declare axis for the column graph
    var axis = {
        id: 'salary',
        min: 0,
        title: {
            text: 'Average Salary',
        },
    };

    // Declare inital series with the values from the getSalaries function
    var series = {
        name: 'Overall',
        data: Object.values(salary),
    };

    var myChart = Highcharts.chart('container', {
        chart: {
            type: 'column',
        },
        title: {
            text: 'Average Salary',
        },
        xAxis: {
            categories: Object.keys(salary),
        },
        yAxis: axis,
        series: [series],
    });

    // On draw, get updated salaries and refresh axis and series
    table.on('draw', function () {
        salary = getSalaries(table);
        myChart.axes[0].categories = Object.keys(salary);
        myChart.series[0].setData(Object.values(salary));
    });
});

function getSalaries(table) {
    var salaryCounts = {};
    var salary = {};

    // Get the row indexes for the rows displayed under the current search
    var indexes = table.rows({ search: 'applied' }).indexes().toArray();

    // For each row, extract the office and add the salary to the array
    for (var i = 0; i < indexes.length; i++) {
        var office = table.cell(indexes[i], 2).data();
        if (salaryCounts[office] === undefined) {
            salaryCounts[office] = [
                +table
                    .cell(indexes[i], 3)
                    .data()
                    .replace(/[^0-9.]/g, ''),
            ];
        } else {
            salaryCounts[office].push(
                +table
                    .cell(indexes[i], 3)
                    .data()
                    .replace(/[^0-9.]/g, '')
            );
        }
    }

    // Extract the office names that are present in the table
    var keys = Object.keys(salaryCounts);

    // For each office work out the average salary
    for (var i = 0; i < keys.length; i++) {
        var length = salaryCounts[keys[i]].length;
        var total = salaryCounts[keys[i]].reduce((a, b) => a + b, 0);
        salary[keys[i]] = total / length;
    }

    return salary;
}

正如我提到的,Highcharts 提供了各种不同的图表类型,通过利用 DataTables API,可以轻松创建动态图表,与 DataTable 一起运行。

希望这将有助于为您的 DataTables 实现添加另一个维度。