本文由Vildan Softic进行同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!
作为Web开发人员,如果您不能错过任何内容,那就是Angular 2 。 它是对Google流行的JavaScript框架的完全重写,并且出于所有正确的原因,它一直是新闻。 与以前的版本相比,它提供了一些重大改进,因此我们今天选择它来构建一些漂亮的图表。
对于图表,我们将使用FusionCharts提供的JavaScript图表库。 它提供了大量图表,并与所有主要浏览器兼容。 尽管FusionCharts 为Angular提供了专用的插件 ,但它尚未与Angular 2兼容。因此,我不打算使用它,而是直接使用JavaScript和Angular 2进行编码。( 注意:如果您正在使用,建议您使用该插件您的应用中的Angular 1 )。
我们将要绘制的图表将描述一个有趣的统计数据-五家顶级高科技公司(亚马逊,苹果,Facebook,谷歌和微软)的收入,并且可以选择在2014年和2015年的收入数据之间进行切换。通过在Angular 2中创建图表的逐步过程。构建基本图表之后,我们将介绍一些高级主题,例如添加注释和更新图表数据。
与以往一样,您可以从我们的GitHub存储库下载本教程的代码,或者可以跳到文章结尾的完成图表的演示 。
Angular 2与以前的主要版本(Angular 1.x)相比有一些重大变化,例如,它对诸如TypeScript和Dart之类的语言的支持,以及它对DOM更新的计算方式。 如果您想了解有关Angular 1概念和技术如何映射到Angular 2的更多信息,可以查看官方快速参考 。 如果您有兴趣将应用程序从Angular 1.x迁移到Angular 2,则可以阅读官方迁移指南 。
尽管Angular 2支持TypeScript和Dart,但由于熟悉,我们将在本教程中使用本机JavaScript编写Angular 2应用程序。 使用TypeScript或Dart也将引入不必要的构建步骤。
有多种方法可以启动和运行Angular 2项目。 最简单的方法可能是前往官方网站,并按照其5分钟快速入门教程进行操作 。
但是,此方法的一个小警告是,它依赖于您在计算机上安装了Node和npm。 我们确实为此提供了指南 ,但是如果您希望在不安装这些指南的情况下遵循本教程,则可以使用以下模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Angular 2 FusionCharts Demo</title>
<!-- 1. Load custom CSS & fonts-->
<link rel="stylesheet" href="styles.css">
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300' rel='stylesheet'>
<!-- 2. Load Angular 2 specific libraries -->
<script src="https://code.angularjs.org/2.0.0-beta.17/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.17/Rx.umd.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.17/angular2-all.umd.dev.js"></script>
<!-- 3. Load FusionCharts library-->
<script src="https://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<!-- 4. Load component -->
<script src='main.js'></script>
</head>
<body>
<!-- 5. Display the application -->
<angular-chart>Loading...</angular-chart>
</body>
</html>
组件是任何Angular 2应用程序的构建块。 它们是由视图和一些逻辑组成的可重用代码段。 如果您熟悉Angular 1,则可以将它们视为带有模板和控制器的指令。
这是图表组件的基础:
(function(chartApp){
chartApp.AppComponent = ng.core.Component({
selector: 'angular-chart',
template: '<div>Chart will render here</div>'
}).Class({
constructor: function(){}
});
document.addEventListener('DOMContentLoaded', function() {
ng.platform.browser.bootstrap(chartApp.AppComponent);
});
})(window.chartApp || (window.chartApp = {}));
让我们花一点时间看看发生了什么。
我们从IIFE( 立即调用的函数表达式 )开始,该IIFE用于给应用程序命名空间。 我们将其传递给window.chartApp
作为参数,如果未定义,则将其初始化为空对象。 这是我们的应用程序将要存在的地方-在全局对象的单个属性中。
在IIFE内部,我们通过链接ng.core
(Angular核心组件的集合)中的Component和Class方法来创建组件( AppComponent
)。 我们正在向Component
方法传递一个包含以下属性的配置对象:
selector
:一个简单的CSS选择器,用于指定宿主HTML元素。 每当遇到与该选择器匹配的HTML元素时,Angular都会创建并显示该组件的实例。
template
:渲染组件时要使用的模板。 当前,我们正在传递一个包含占位符<div>
元素的字符串,但是理想情况下,我们应该将其移到其自己的模板中。
在Class
方法中,我们为模板添加行为和事件绑定。
定义了基本组件之后,我们将使用Angular的浏览器启动函数对其进行初始化。
此时,您应该能够在浏览器中运行代码,并看到消息“图将在此处呈现”。
让我们继续创建图表并显示2014年的一些数据。
为此,我们需要使用FusionCharts构造函数 ,向该函数传递一个对象,该对象包含图表实例的所有配置参数:
type
:我们希望创建的图表类型 renderAt
:将图表渲染到的DOM选择器 width
和height
:图表尺寸 id
:生成的图表的ID dataFormat
:传递给dataSource
选项的数据格式 dataSource
:实际图表的配置及其应显示的数据 new FusionCharts({
"type": "column2d",
"renderAt": "chart-container",
"width": "550",
"height": "400",
"id": "revenue-chart",
"dataFormat": "json",
"dataSource": {
"chart": {
"yAxisName": "Revenue (In USD Billion)",
"yAxisMaxValue": "200",
...
},
"data": [{
"label": "Amazon",
"value": "88.99"
}, {
"label": "Apple",
"value": "182.8"
}
...
]
}
});
这是完整的配置文件 。
如果不确定任何chart
选项的实际作用,或者不确定如何配置图表外观,请参考FusionCharts文档中的“ 图表属性”页面。
我们要做的另一件事是更新模板,以包括图表应呈现到的容器。 您可以通过为Component的template
属性指定一个字符串来完成此操作(就像我们之前所做的那样),也可以将模板移到其自己的文件中并使用templateUrl
对其进行引用。
chartApp.AppComponent = ng.core.Component({
selector: 'angular-chart',
templateUrl: 'chart.html'
}).Class({
...
});
无论哪种方式,这都是我们的模板的外观。
<div class="container">
<h1>Revenue of Top Tech Companies (2014)</h1>
<div id ="chart-container"></div>
</div>
这是到目前为止的演示:
您可以在Plunker上查看此演示的代码 。
如果单击Plunker上的演示,可能会注意到在文件main.js
,我们已将FusionCharts配置数据分离到其自己的文件中,然后使用Angular的HTTP类进行获取。 这是为了清楚起见(它使Angular特定的代码更易于遵循),也因为对数据的请求是您在现实生活中通常要做的。
但是,这不是绝对必要的,通过直接在chartApp
构造函数中执行所有操作,您将获得相同的结果:
(function(chartApp) {
chartApp.AppComponent = ng.core.Component({
selector: 'angular-chart',
template: '<div class="container"><h1>Revenue of Top Tech Companies (2014)</h1><div id ="chart-container"></div></div>'
}).Class({
constructor: function() {
FusionCharts.ready(function(){
var revenueChart = new FusionCharts({
// config data here
}).render();
});
}
});
document.addEventListener('DOMContentLoaded', function() {
ng.platform.browser.bootstrap(chartApp.AppComponent);
});
})(window.chartApp || (window.chartApp = {}));
唯一要提及的是,初始化代码包含在FusionCharts.ready
方法中。 这样可以防止在加载FusionCharts库之前调用图表实例化代码。
准备好基本图表后,就该添加更多功能了,例如使用公司徽标代替名称,并使用2015年的新数据更新图表。
要将公司徽标添加到x轴,我们将使用FusionCharts的强大功能之一- 注解 。 通过FusionCharts对象上的注释,您可以在图表上的指定位置绘制自定义形状或图像。
假设您想在图表中心添加公司徽标。 您可以使用批注和宏来实现 。 宏将为您提供图表中心的坐标,而注释将使您可以在该位置添加图像。
当您使用动态注释来获取例如依赖于图表数据的位置信息时,事情会变得很有趣。 想象一下,您想在列的确切位置绘制一些内容。 您可以使用动态注释宏$dataset.0.set.1.endX
和$dataset.0.set.1.endY
来确定列端点的x和y坐标,然后在该端点上绘制一些内容。 您可以在此FusionCharts文档页面上了解有关注释以及如何使用它们的更多信息。
对于我们的图表,我们将使用动态注释宏来获取每一列的开始和结束坐标,然后在此处绘制各自的公司徽标。 我们还将使用图表属性"showLabels": "0"
禁用默认的x轴标签。
为了实现上述目标,请将以下代码添加到图表的配置中:
{
"type": "column2d",
...
"dataSource": {
"chart": {
"showLabels": "0",
...
},
"data": [{ ... }],
"annotations": {
"groups": [{
"id": "logo-images",
"xScale": "30",
"yScale": "30",
"showBelow": "0",
"items": [{
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735364amazon.jpg",
"x": "$dataset.0.set.0.startx + 25",
"y": "$dataset.0.set.0.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735362apple.jpg",
"x": "$dataset.0.set.1.startx + 85",
"y": "$dataset.0.set.1.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735369facebook.jpg",
"x": "$dataset.0.set.2.startx + 20",
"y": "$dataset.0.set.2.endY + 10"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735358google.jpg",
"x": "$dataset.0.set.3.startx + 5",
"y": "$dataset.0.set.3.endY + 5"
}, {
"type": "image",
"url": "https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2016/06/1465735372microsoft.jpg",
"x": "$dataset.0.set.4.startx + 30",
"y": "$dataset.0.set.4.endY + 10"
}]
}]
}
}
}
在上面的代码中:
type
设置注释的类型。 url
设置图像的地址。 x
和y
设置图像的起始x和y坐标。 添加以上代码后,您应该看到在x轴上呈现的公司徽标。 要了解有关使用注释的更多信息以及其他可能的方法,请参考文档页面 (上述)。
我们要实现的最后一件事是允许用户在年份之间切换,根据所选年份(2014或2015)查看不同的数据集。
因此,我们需要考虑如何以可以定义不同年份的不同数据集的方式来构造数据。 如前所述,FusionCharts期望配置选项包含一个data
属性,该属性应该是一个包含标签/值对集合的数组。
{
"type": "column2d",
...
"dataSource": {
"chart": {},
"data": [
{
"label": "whatever",
"value": "a value"
}
]
}
}
处理多个数据集的一种方法是在构造函数的顶部定义一个dataSet
对象,并使用别名将其附加到构造函数。
var chartComp= this;
chartComp.dataSet = {
"2014": [{
"label": "Amazon",
"value": "88.99"
}, {
"label": "Apple",
"value": "182.8"
}, {
"label": "Facebook",
"value": "12.47"
}, {
"label": "Google",
"value": "65.67"
}, {
"label": "Microsoft",
"value": "86.83"
}],
"2015": [{
"label": "Amazon",
"value": "107.01"
}, {
"label": "Apple",
"value": "233.72"
}, {
"label": "Facebook",
"value": "17.93"
}, {
"label": "Google",
"value": "74.54"
}, {
"label": "Microsoft",
"value": "93.58"
}]
}
然后,在配置选项中传递给FusionCharts构造函数,我们可以执行以下操作:
"data": chartComp.dataSet['2014'],
我们也希望图表与2015年的数据,一旦有人点击了2015年按钮,切换回显示了2014年,被点击2014年按钮时的数据进行更新。
让我们添加两个按钮,这两个按钮将用于执行此操作并为其提供样式 。 修改组件模板,如下所示:
<div class="container">
<h1>Revenue of Top Tech-companies</h1>
<div class="actions">
<button (click)="yearChange(2014)"
[ngClass] = "{selected: selectedYear== 2014}">2014
</button>
<button (click)="yearChange(2015)"
[ngClass] = "{selected: selectedYear== 2015}">2015
</button>
</div>
<div id ="chart-container"></div>
</div>
请注意,在Angular 2中添加了事件侦听器并添加了ngClass指令的新语法。它们与Angular 1几乎相同,但有一些括号和括号。
我添加了一个ngClass
指令,通过将selected
CSS类应用于按钮元素来突出显示当前选定的年份。 这基于组件上的selectedYear
属性,该属性在单击按钮后即会更新。
通过将以下行添加到构造函数的顶部,我们可以将组件选择的当前年份设置为2014年:
chartComp.selectedYear = 2014;
处理按钮单击的逻辑将添加到new yearChange
函数中。
.Class({
constructor: function(){ ... },
yearChange: function(){ // button logic here }
);
为此,我们将使用FusionChart的setChartData方法,该方法同时需要图表配置选项和实际图表数据。 我们将使用getChartData
方法从已呈现的图表中获取图表属性,而不是先存储图表属性然后再引用它们,而是使用特定年份的数据修改该数据。
yearChange: function(year) {
var revenueChart = FusionCharts.items['revenue-chart'];
var chartJson = revenueChart.getChartData('json');
chartJson.data = this.dataSet[year];
revenueChart.setChartData(chartJson);
this.selectedYear = year;
}
在添加按钮的HTML和上述按钮的单击处理程序之后,单击这些按钮应加载该图表的当年数据。
这是最终的演示。
您可以在Plunker上查看此演示的代码 。 或者,您可以从我们的GitHub存储库下载代码。
如果单击进入Plunker,您将看到我们已经直接在config.json文件中定义了dataSet
属性。 这使我们的组件变得更加整洁。
我们首先构建一个简单的Angular图表,然后使用注释和其他FusionCharts的API向其添加更多功能。 但这只是冰山一角,使用Angular 2和FusionCharts可以完成更多工作。 您可以自己探索一些东西:
包括更多图表:柱形图并不总是代表数据集的最佳方法。 根据您的用例,您可能希望使用不同的图表,例如瀑布图,雷达图,量规等。因此,请尝试使用本教程中说明的过程来绘制不同的图表,并查看是否能够成功完成该过程。
在您的应用程序中包含图表:如果您要制作混合移动应用程序,则必须意识到Ionic 2 (最新版本的Ionic)基于Angular2。这是一个好消息,因为您可以使用本教程作为基础也为您的Ionic应用程序创建图表。
探索更多事件:在本教程中,我解释了如何使用setChartData
方法,但是您可以使用许多其他事件和方法来增强应用程序的用户体验。 查看上面的链接页面,以了解有关FusionCharts提供的各种事件和方法的更多信息。
如果您在尝试自己制作图表时遇到任何困难,请参阅Angular或FusionCharts的文档(取决于问题),或者在下面发表评论。 我将竭诚为您服务!
From: https://www.sitepoint.com/chart-component-angular2-fusioncharts/