AnyChart 是基于JavaScript (HTML5) 的图表控件。使用AnyChart控件,可创建跨浏览器和跨平台的交互式图表和仪表。AnyChart 图表目前已被很多知名大公司所使用,可用于仪表盘、报表、数据分析、统计学、金融等领域。


本文是一个循序渐进的指南,将向您展示如何构建一个交互式JavaScript范围图,以可视化方式显示洛杉矶湖人队20年来科比·布莱恩特的表现。

出于明显的原因,2020年是非常凄惨的一年。但是,甚至在疫情之前,篮球传奇人物科比·布莱恩特(Kobe Bryant)的去世,这一年就开始令人难过。他是NBA的明星球员,曾与洛杉矶湖人队(Los Angeles Lakers)一起效力过20年。

在那次可怕的车祸发生一年后,我想起了科比,我想知道湖人在他的两个十年中的表现如何。因此,在纯JavaScript的帮助下,我在交互式Divingging Bar Chart中可视化了这一点。

考虑到该项目可能对Web制图的新手有所帮助,我还记录了整个过程并制作了一个教程。一探究竟!

什么是发散条形图?

首先,我将简要介绍什么是不同的条形图,然后我们将深入研究本教程。

发散的条形图显示了从中间基线绘制的两个或多个度量,向右和向左(水平范围条)或顶部和底部(垂直范围列)延伸。

在这种不同的图表中,数据可视化的关键点是通过针对分叉的中点显示它们来促进多个类别的比较。

在本教程中,我将使用分散的条形图技术来展示在科比·布莱恩特20年职业生涯中洛杉矶湖人队的得失。

这是最后一张图表的速览,让您为比赛的开始做好准备!跟着我学习如何使用JavaScript创建这个漂亮的范围条形图。

éæ¬JSå¾è¡¨æç¨ä¸èµ·å建HTML5 JavaScript Divergingæ¡å½¢å¾æ°æ®å¯è§å

如何通过4个基本步骤构建JavaScript分流条形图

那里有多个JavaScript库,它们为常用功能提供了预编写的JS代码,这些代码可以使交互式数据可视化过程变得非常快速和直接。

我选择了一个名为AnyChart的图表来创建此分散的条形图。这个JS图表库似乎开箱即用地支持(在这种情况下特别有用)范围图,并且还足够灵活地执行我想要的操作。

而且,即使对于初学者来说,也很容易上手AnyChart,因为这里有很多现成的示例,并且包含大量文档。

当然,拥有良好的HTML和JavaScript技能可以使您在Web上可视化数据时具有优势。但是无论如何,关于使用好的图表库的最好的部分是,即使没有太多的经验,它们也使创建交互式图表变得相当简单。

几乎可以创建任何JS图表的整个过程,包括像这样的分散条形图,可以分为四个基本步骤:

  1. 创建一个HTML页面。
  2. 参考必要的JS文件。
  3. 设置数据。
  4. 编写图表的JS代码。

现在让我们详细介绍每个步骤。

1.创建一个基本的HTML页面

我们需要做的第一件事是创建一个基本的HTML页面。让我们给它一个标题,并创建一个HTML块元素来保存图表。为了<div>在以后的代码中识别出这一点,我们还应该给它一个id属性(让它成为“容器”)。

<html>
  <head>
    <title>JavaScript Diverging Bar Chart</title>
    <style type="text/css">      
        html, body, #container { 
            width: 100%; height: 100%; margin: 0; padding: 0; 
        } 
    </style>
  </head>
  <body>
    <div id="container"></div>
  </body>
</html>

请注意,可以在<style>块内指定width和height参数来修改图表将占用的空间。我在两个参数中都输入了100%,因此图表占据了整个页面。

2.包含必要的JavaScript文件

接下来,我们需要添加图表库脚本,这将有助于创建数据可视化。由于我们在这里使用AnyChart库,因此让我们包括CDN中的相应文件。(请记住,如果需要,您始终可以下载脚本。)

对于不同的条形图,我们需要基本模块脚本,该脚本将添加到<head>HTML页面的部分中。

<html>
  <head>
    <title>JavaScript Diverging Bar Chart</title>
    <script src="https://cdn.anychart.com/releases/8.9.0/js/anychart-base.min.js" type="text/javascript"></script>
    <style type="text/css">
      html,
      body,
      #container {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>  
    <div id="container"></div>
    <script>
      // All the code for the JS diverging bar chart will come here
    </script>
  </body>
</html>

3.添加数据
我想将1996年至2016年整个赛季洛杉矶湖人队的获胜和失败人数可视化。因此,我从NBA网站获取了数据,并创建了包含年份,获胜和失败的数组。

由于数据量不是很大,所以我们可以像这样添加它:

var winlossData = [
  [65, 17, "2015-16"],
  [61, 21, "2014-15"],
  [55, 27, "2013-14"],
  [37, 45, "2012-13"],
  [25, 41, "2011-12"],
  [25, 57, "2010-11"],
  [25, 57, "2009-10"],
  [17, 65, "2008-09"],
  [25, 57, "2007-08"],
  [40, 42, "2006-07"],
  [37, 45, "2005-06"],
  [48, 34, "2004-05"],
  [26, 56, "2003-04"],
  [32, 50, "2002-03"],
  [24, 58, "2001-02"],
  [26, 56, "2000-01"],
  [15, 67, "1999-00"],
  [19, 31, "1998-99"],
  [21, 61, "1997-98"],
  [26, 56, "1996-97"]
];

现在已经准备好阶段,让我们开始添加可创建交互式Diverging Bar Chart的JavaScript代码!

4.编写图表的JavaScript代码

首先,我们需要添加一个包含所有JS代码的函数,以确保其中的整个代码仅在页面加载后才能执行。

<script>
  anychart.onDocumentReady(function() {
    // The place for the JS diverging bar chart code
  });
</script>

通常,创建JS分散条形图非常容易,我将逐步指导您完成每个操作。因此,准备扭动,阻挡和射击!

首先,我们创建一个条形图并在封闭anychart.onDocumentReady()函数内部输入数据。

// create a bar chart
var chart = anychart.bar();

// data
var winlossData = [
  [65, 17, "2015-16"],
  [61, 21, "2014-15"],
  [55, 27, "2013-14"],
  [37, 45, "2012-13"],
  [25, 41, "2011-12"],
  [25, 57, "2010-11"],
  [25, 57, "2009-10"],
  [17, 65, "2008-09"],
  [25, 57, "2007-08"],
  [40, 42, "2006-07"],
  [37, 45, "2005-06"],
  [48, 34, "2004-05"],
  [26, 56, "2003-04"],
  [32, 50, "2002-03"],
  [24, 58, "2001-02"],
  [26, 56, "2000-01"],
  [15, 67, "1999-00"],
  [19, 31, "1998-99"],
  [21, 61, "1997-98"],
  [26, 56, "1996-97"]
];

接下来,我们创建一个接受两个参数的函数-列号和名称。列号指示数据集中的列,名称指示序列。在我们的案例中,我们有两个系列-一个代表获胜次数,一个代表失落次数。

因为我们想要一个分散的条形图,所以让我们以中心为坐标,在右边绘制获胜的条形图,在左边绘制损失的条形图。然后,我们应该通过“ for”循环添加所有必需的值来准备数据集。

如果这听起来有点复杂,请不要担心。这只是要准备好我们的数据进行绘制,当您查看下面的代码时,您可能会发现它们完全是合乎逻辑的。

我们还需要在函数中包含两件事。我们使用该rangeBar函数定义了一个系列,并添加了一行以指示该系列的名称,并在左右条之间添加了分隔线。

var createSeries = function (columnNumber, name) {
  var data = [];
  for (var i = 0; i < winlossData.length; i++) {
    var value = winlossData[i][columnNumber];
    var center = 0;
    if (name === "Wins") {
      data.push({
        x: winlossData[i][2],
        low: center,
        high: center + value,
        value: value
      });
    } else {
      data.push({
        x: winlossData[i][2],
        low: -center,
        high: -center - value,
        value: value
      });
    }
  }
    
  var series = chart.rangeBar(data);
  series.name(name);
};

现在,我们使用刚刚定义的函数用所需的参数创建两个系列。

createSeries(0, "Losses");
createSeries(1, "Wins");

中场休息,最复杂的部分结束了!现在,我们有了图表的设置。

将标题添加到不同的条形图中:

chart
  .title()
  .enabled(true)
  .text("20 Years of LA Lakers Win-Loss Record with Kobe Bryant (1996-2016)");

并启用图表的图例:

chart
  .legend()
  .enabled(true);

为了使每年的赢利彼此相邻,我们应该将多系列条形图转换为堆积的条形图。接下来,为了强调差异,让我们在0处添加一个线标记。最后,我们分配容器div并绘制图表:

// create a stacked bar chart from the multi-series bar chart
chart.yScale().stackMode("value");

// set a container id for the chart
chart.container("container");
  
// initiate chart drawing
chart.draw();

这就是哨子了,这就是用JavaScript构建的非常基本但功能齐全的交互式发散条形图!

尽管科比在他职业生涯的最后几场比赛中表现出色,但我们可以看到湖人在他过去的几年中苦苦挣扎,亏损多于胜利。但是总的记录肯定比失败多得多。

请看一下此散布条形图的初始版本,以及在CodePen [或在AnyChart Playground ]上的完整JS / CSS / HTML代码。

<html>
  <head>
    <title>JavaScript Diverging Bar Chart</title>
    <script src="https://cdn.anychart.com/releases/8.9.0/js/anychart-base.min.js" type="text/javascript"></script>
    <style type="text/css">
      html,
      body,
      #container {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>  
    <div id="container"></div>
    <script>

    anychart.onDocumentReady(function () {
  
      // create a bar chart
      var chart = anychart.bar();

      // data
      var winlossData = [
        [65, 17, "2015-16"],
        [61, 21, "2014-15"],
        [55, 27, "2013-14"],
        [37, 45, "2012-13"],
        [25, 41, "2011-12"],
        [25, 57, "2010-11"],
        [25, 57, "2009-10"],
        [17, 65, "2008-09"],
        [25, 57, "2007-08"],
        [40, 42, "2006-07"],
        [37, 45, "2005-06"],
        [48, 34, "2004-05"],
        [26, 56, "2003-04"],
        [32, 50, "2002-03"],
        [24, 58, "2001-02"],
        [26, 56, "2000-01"],
        [15, 67, "1999-00"],
        [19, 31, "1998-99"],
        [21, 61, "1997-98"],
        [26, 56, "1996-97"]
      ];

      // configure a function to create series
      var createSeries = function (columnNumber, name) {
        var data = [];
        for (var i = 0; i < winlossData.length; i++) {
          var value = winlossData[i][columnNumber];
          var center = 0;
          if (name === "Wins") {
            data.push({
              x: winlossData[i][2],
              low: center,
              high: center + value,
              value: value
            });
          } else {
            data.push({
              x: winlossData[i][2],
              low: -center,
              high: -center - value,
              value: value
            });
          }
        }
    
        var series = chart.rangeBar(data);
        series.name(name);
      };

      // create series
      createSeries(0, "Losses");
      createSeries(1, "Wins");

      // set the chart title
     chart
        .title()
        .enabled(true)
        .text("20 Years of LA Lakers Win-Loss Record with Kobe Bryant (1996-2016)");

      // enable the chart legend
      chart
        .legend()
        .enabled(true);
  
      // create a stacked bar chart from the multi-series bar chart
      chart.yScale().stackMode("value");

      // set a container id for the chart
      chart.container("container");
  
      // initiate chart drawing
      chart.draw();

    });

    </script>
  </body>
</html>

如何自定义我们的JavaScript分散条形图

关于使用JavaScript进行交互式数据可视化的一个扣篮,是我们必须自定义它的自由,以便我们的数据能够讲述更好的故事。我将向您展示如何对基于JS的基本发散条形图进行一些快速更改,以使其更具吸引力和信息量。

现在,我将抛出一个三指针并自定义图表以改善其某些功能和美观性。

1.基本样式和轴设置

首先,让我们更改X和Y轴的一些基本样式和设置,以使内容更具可读性。

只要记住,在AnyChart的,一个范围条形图是垂直版本范围柱形图。因此,在我们的分散条形图中,水平轴为Y轴,垂直轴为X轴。

因此,让我们摆脱刻度线,配置轴标题,并自定义垂直轴上的标签。我们还将最大值设置为80,并从水平轴上的标签中删除减号:

chart
  .xAxis()
  .ticks(false);
chart
  .xAxis()
  .title()
  .enabled(true)
  .text("Years")
  .padding([0, 0, 10, 0]);
chart
  .xAxis()
  .labels()
  .fontSize(11)
  .fontColor("#474747")
  .padding([0, 10, 0, 0]);
chart.yScale().maximum(80);
chart
  .yAxis(0)
  .labels()
  .format(function () {
    return Math.abs(this.value);
  });

接下来,为了强调差异,最好在两个系列之间添加一个白色描边,并在0处添加一个线标记。

// add the stroke by setting it in this line
series.name(name).stroke("3 #fff 1");

...

// create a line marker at 0
chart
  .lineMarker()
  .value(0)
  .stroke("#CECECE");

在我们进行更多自定义之前,我需要做一个小题外话。我还想到了使水平轴以百分比而不是绝对值显示每个赛季的获利和损失。这很容易,但是结果并没有提供任何额外的见解。

而且,绝对值确实代表了湖人队一年中玩多少场比赛。最终,这就是为什么我决定保留绝对值的原因。但是欢迎您在CodePen [或AnyChart Playground ]上查看带有百分比的版本。

好吧,让我们从错过的镜头继续前进,然后回到对焦模式。

2.工具提示自定义

接下来,我自定义了工具提示,以使其内容更丰富,更有趣。

在这里,我还想到了将先前计算出的百分比值(请参阅上面的示例)作为我们分散的条形图工具提示中的额外信息展示的想法。

因此,第一步是实现百分比值的计算:

// calculate percentages for the tooltip
var val = winlossData[i][columnNumber] * 100;
if (columnNumber == 0) {
  var percentValue =
    val / (winlossData[i][columnNumber] + winlossData[i][columnNumber + 1]);
} else {
  var percentValue =
    val / (winlossData[i][columnNumber] + winlossData[i][columnNumber - 1]);
}
percentValue = percentValue.toFixed(2);

百分比计算是系列配置功能的一部分-查看它如何包含在其中:

// configure a function to create series
var createSeries = function (columnNumber, name) {
  var data = [];
  for (var i = 0; i < winlossData.length; i++) {

    // calculate percentages for the tooltip
    var val = winlossData[i][columnNumber] * 100;
    if (columnNumber == 0) {
      var percentValue =
        val / (winlossData[i][columnNumber] + winlossData[i][columnNumber + 1]);
    } else {
      var percentValue =
        val / (winlossData[i][columnNumber] + winlossData[i][columnNumber - 1]);
    }
    percentValue = percentValue.toFixed(2);     
      
    var value = winlossData[i][columnNumber];
    var center = 0;
    if (name === "Wins") {
      data.push({
        x: winlossData[i][2],
        low: center,
        high: center + value,
        value: value,
        // add the calculated percentage value
        percentValue: percentValue
      });
    } else {
      data.push({
        x: winlossData[i][2],
        low: -center,
        high: -center - value,
        value: value,
        // add the calculated percentage value
        percentValue: percentValue
      });
    }
  }

然后,我们还提供了其他工具提示格式,以使它们看起来既整洁又美观:

// customize the tooltip
chart
  .tooltip()
  .useHtml(true)
  .fontSize(12)
  .titleFormat(function () {
    return this.getData("x") + " " + this.seriesName;
  })
  .format(function () {
    return (
      "<h6 style='font-size:12px; font-weight:400; margin: 0.25rem 0;'>Total games: " +
      "<b>" +
      this.getData("value") +
      "</b></h6>" +
      "<h6 style='font-size:12px; font-weight:400; margin: 0.25rem 0;'>Percentage games: " +
      "<b>" +
      this.getData("percentValue") +
      " %</b></h6>"
    );
  });

3.调色板更改

好吧,最后一次自定义绝对是一把匕首-这张照片将使这张图表看起来非常棒,并赢得比赛!它只是在更改调色板以匹配洛杉矶湖人队球衣的颜色。很简单:

chart.palette(
  anychart.palettes.distinctColors().items(["#FDB827", "#542583"])
);

series.name(name).stroke("3 #fff 1").selectionMode("none");

好的!最终的交互式JavaScript差异范围条形图可在CodePen [和AnyChart Playground ]上获得。

以防万一,HTML页面的完整代码就在这里:

<html>
  <head>
    <title>JavaScript Diverging Bar Chart</title>
    <script src="https://cdn.anychart.com/releases/8.9.0/js/anychart-base.min.js" type="text/javascript"></script>
    <style type="text/css">
      html,
      body,
      #container {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>  
    <div id="container"></div>
    <script>

    anychart.onDocumentReady(function () {
  
      // create a bar chart
      var chart = anychart.bar();

      // data
      var winlossData = [
        [65, 17, "2015-16"],
        [61, 21, "2014-15"],
        [55, 27, "2013-14"],
        [37, 45, "2012-13"],
        [25, 41, "2011-12"],
        [25, 57, "2010-11"],
        [25, 57, "2009-10"],
        [17, 65, "2008-09"],
        [25, 57, "2007-08"],
        [40, 42, "2006-07"],
        [37, 45, "2005-06"],
        [48, 34, "2004-05"],
        [26, 56, "2003-04"],
        [32, 50, "2002-03"],
        [24, 58, "2001-02"],
        [26, 56, "2000-01"],
        [15, 67, "1999-00"],
        [19, 31, "1998-99"],
        [21, 61, "1997-98"],
        [26, 56, "1996-97"]
      ];

      // configure a function to create series
      var createSeries = function (columnNumber, name) {
        var data = [];
        for (var i = 0; i < winlossData.length; i++) {

          // calculate percentages for the tooltip
          var val = winlossData[i][columnNumber] * 100;
          if (columnNumber == 0) {
            var percentValue =
              val / (winlossData[i][columnNumber] + winlossData[i][columnNumber + 1]);
          } else {
            var percentValue =
              val / (winlossData[i][columnNumber] + winlossData[i][columnNumber - 1]);
          }
          percentValue = percentValue.toFixed(2);     
      
          var value = winlossData[i][columnNumber];
          var center = 0;
          if (name === "Wins") {
            data.push({
              x: winlossData[i][2],
              low: center,
              high: center + value,
              value: value,
              // add the calculated percentage value
              percentValue: percentValue
            });
          } else {
            data.push({
              x: winlossData[i][2],
              low: -center,
              high: -center - value,
              value: value,
              // add the calculated percentage value
              percentValue: percentValue
            });
          }
        }
    
        var series = chart.rangeBar(data);
        series.name(name).stroke("3 #fff 1").selectionMode("none");
      };

      // create series
      createSeries(0, "Losses");
      createSeries(1, "Wins");

      // set the chart title
      chart
        .title()
        .enabled(true)
        .text("20 Years of LA Lakers Win-Loss Record with Kobe Bryant (1996-2016)");

      // enable the chart legend
      chart
        .legend()
        .enabled(true);
  
      // create a stacked bar chart from the multi-series bar chart
      chart.yScale().stackMode("value");
  
      // customize the settings of the axes
      chart
        .xAxis()
        .ticks(false);
      chart
        .xAxis()
        .title()
        .enabled(true)
        .text("Years")
        .padding([0, 0, 10, 0]);
      chart
        .xAxis()
        .labels()
        .fontSize(11)
        .fontColor("#474747")
        .padding([0, 10, 0, 0]);
      chart.yScale().maximum(80);
      chart
        .yAxis(0)
        .labels()
        .format(function () {
          return Math.abs(this.value);
        });

      // create a line marker at 0
      chart
        .lineMarker()
        .value(0)
        .stroke("#CECECE");
  
      // customize the tooltip
      chart
        .tooltip()
        .useHtml(true)
        .fontSize(12)
        .titleFormat(function () {
          return this.getData("x") + " " + this.seriesName;
        })
        .format(function () {
          return (
            "<h6 style='font-size:12px; font-weight:400; margin: 0.25rem 0;'>Total games: " +
            "<b>" +
            this.getData("value") +
            "</b></h6>" +
            "<h6 style='font-size:12px; font-weight:400; margin: 0.25rem 0;'>Percentage games: " +
            "<b>" +
            this.getData("percentValue") +
            " %</b></h6>"
          );
        });
  
      // set a custom color palette
      chart.palette(
        anychart.palettes.distinctColors().items(["#FDB827", "#542583"])
      );

      // set a container id for the chart
      chart.container("container");
  
      // initiate chart drawing
      chart.draw();

    });

    </script>
  </body>
</html>

结论

在本教程中,我向您展示了使用JavaScript建立并运行分散的条形图是多么快速和容易。我们还看到了一点点的努力如何使图形看起来真的很酷,并使您从基础数据中获得更多收益。请让我知道,如果你有任何问题。

如果您有动力与更多基于JS的交互式数据可视化一起工作,请继续并尝试使用CodePen上不同的条形图(我在本教程中添加了链接),查看其他图表选项,或尝试其他JavaScript库。

另外,当我们在这里回顾篮球传奇球队的统计数据时,请记住要进行更多的运动并创建更多的可视化效果。