FlexChart 101

入门

在AngularJS应用中开始使用FlexChart的步骤:

  1. 为AngularJS,Wijmo和Wijmo的AngularJS指令添加引用。
  2. 在应用模块中包含Wijmo 5指令:
    var app = angular.module('app', ['wj']);
  3. 添加一个控制器来提供数据和逻辑
  4. 向当前页面添加一个FlexChart,并且将它与数据绑定。
  5. 添加一些CSS来个性化图表的外观。
<html> <head> <link rel="stylesheet" href="css/bootstrap.css"/> <link rel="stylesheet" href="css/wijmo.css"/> <link href="css/app.css" rel="stylesheet"/> <script src="scripts/angular.js"></script> <script src="scripts/wijmo.js"></script> <script src="scripts/wijmo.chart.js"></script> <script src="scripts/wijmo.angular.js"></script> <script src="scripts/app.js"></script> </head> <body ng-app="app" ng-controller="appCtrl"> <!-- this is the chart --> <wj-flex-chart items-source="data" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"> </wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"> </wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"> </wj-flex-chart-series> </wj-flex-chart> </body> </html>
// declare app module var app = angular.module('app', ['wj']); // app controller provides data app.controller('appCtrl', function appCtrl($scope) { // generate some random data var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','), data = []; for (var i = 0; i < countries.length; i++) { data.push({ country: countries[i], downloads: Math.round(Math.random() * 20000), sales: Math.random() * 10000, expenses: Math.random() * 5000 }); } // add data array to scope $scope.data = data; });
/* set default chart style */ .wj-flexchart { height: 400px; background-color: white; box-shadow: 4px 4px 10px 0px rgba(50, 50, 50, 0.75); padding: 8px; margin-bottom: 12px; }

结果:

图表类型

FlexChart控件有三个属性允许你来自定义图表的类型:

  1. chartType:对于所有系列对象选择默认的图表类型。个别系列对象可以覆盖它。
  2. stacking: 确定系列对象是否独立地绘制,堆积或百分比堆积。
  3. rotated: 翻转X轴和Y轴,导致X变为垂直,Y变为水平。

以下这个示例允许你查看当你改变这些属性的效果:

<wj-flex-chart items-source="data" chart-type="{{chartProps.chartType}}" stacking="{{chartProps.stacking}}" rotated="{{chartProps.rotated}}" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"> </wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"> </wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"> </wj-flex-chart-series> </wj-flex-chart> <wj-menu value="chartProps.chartType" header="图表类型" > <wj-menu-item value="0">Column</wj-menu-item> <wj-menu-item value="1">Bar</wj-menu-item> <wj-menu-item value="2">Scatter</wj-menu-item> <wj-menu-item value="3">Line</wj-menu-item> <wj-menu-item value="4">LineSymbols</wj-menu-item> <wj-menu-item value="5">Area</wj-menu-item> <wj-menu-item value="9">Spline</wj-menu-item> <wj-menu-item value="10">SplineSymbols</wj-menu-item> <wj-menu-item value="11">SplineArea</wj-menu-item> </wj-menu> <wj-menu value="chartProps.stacking" header="堆积" > <wj-menu-item value="0">无</wj-menu-item> <wj-menu-item value="1">堆积</wj-menu-item> <wj-menu-item value="2">百分比堆积</wj-menu-item> </wj-menu> <wj-menu value="chartProps.rotated" header="是否旋转" > <wj-menu-item value="false">False</wj-menu-item> <wj-menu-item value="true">True</wj-menu-item> </wj-menu>
// add chart properties to scope $scope.chartProps = { chartType: wijmo.chart.ChartType.Column, stacking: wijmo.chart.Stacking.None, rotated: false };

结果:

Column Bar Scatter Line LineSymbols Area Spline SplineSymbols SplineArea 堆积 百分比堆积 False True

漏斗图

以下示例说明了如何创建和自定漏斗图:

<wj-flex-chart control="funnelChart" items-source="funnelData" chart-type="Funnel" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> </wj-flex-chart> <dl class="dl-horizontal"> <dt>Neck Width</dt> <dd> <div id="funnelNeckWidth"></div> <wj-input-number control="inputNeckWidth" value="neckWidth" min="0" max="1" step=".1"> </wj-input-number> </dd> </dl> <dl class="dl-horizontal"> <dt>Neck Height</dt> <dd> <div id="funnelNeckHeight"></div> <wj-input-number control="inputNeckHeight" value="neckHeight" min="0" max="1" step=".1"> </wj-input-number> </dd> </dl> <dl class="dl-horizontal"> <dt></dt> <dd> <wj-menu header="Funnel Type: <b>{{ funnelType }}</b>" item-clicked="funnelTypeChanged(s, e)"> <wj-menu-item value="'default'">Default</wj-menu-item> <wj-menu-item value="'rectangle'">Rectangle</wj-menu-item> </wj-menu> </dd> </dl>
$scope.funnelChart = null; $scope.inputNeckWidth = null; $scope.inputNeckHeight = null; $scope.neckWidth = 0.2; $scope.neckHeight = 0.2; $scope.funnelType = 'default'; $scope.$watch('funnelChart', function () { var funnelChart = $scope.funnelChart; if (funnelChart != null) { funnelChart.options = { funnel: { neckWidth: 0.2, neckHeight: 0.2, type: 'default' } }; funnelChart.dataLabel.content = '{y}'; } }); $scope.$watch('neckWidth', function () { var neckWidth = $scope.inputNeckWidth, val = $scope.neckWidth; if (neckWidth != null) { if (val < neckWidth.min || val > neckWidth.max) { return; } $scope.funnelChart.options.funnel.neckWidth = val; $scope.funnelChart.refresh(true); } }); $scope.$watch('neckHeight', function () { var neckHeight = $scope.inputNeckHeight, val = $scope.neckHeight; if (neckHeight != null) { if (val < neckHeight.min || val > neckHeight.max) { return; } $scope.funnelChart.options.funnel.neckHeight = val; $scope.funnelChart.refresh(true); } }); $scope.funnelTypeChanged = function (sender) { $scope.funnelChart.options.funnel.type = sender.selectedValue; $scope.funnelChart.refresh(true); };

Result (live):

领宽
领高
Default Rectangle

混合图表类型

你可以对每个图表系列使用不同的图表类型,这是通过对它这个系列本身设置chartType属性。 这会覆盖图表的默认图表类型。

在以下的示例,这个图表的chartType属性被设为Column, 但是Downloads系列使用了LineAndSymbol类型覆盖它:

<wj-flex-chart items-source="data" chart-type="Column" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads" chart-type="LineSymbols"></wj-flex-chart-series> </wj-flex-chart>

结果:

图例和标题

使用legend属性来自定义图表图例的外观, 使用headerfooter和坐标的title属性来向你的图表添加标题。

你可以使用CSS来确定图例和标题的样式。下面的CSS标签显示用于自定义图例和标题的外观的规则。 注意它们是SVG元素,所以你必须使用”fill”这样的CSS属性而不是”color”。

<wj-flex-chart items-source="data" binding-x="country" header="{{chartProps.header}}" footer="{{chartProps.footer}}"> <wj-flex-chart-legend position="{{chartProps.legendPosition}}"> </wj-flex-chart-legend> <wj-flex-chart-axis wj-property="axisX" title="{{chartProps.titleX}}"> </wj-flex-chart-axis> <wj-flex-chart-axis wj-property="axisY" title="{{chartProps.titleY}}"> </wj-flex-chart-axis> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"></wj-flex-chart-series> </wj-flex-chart> <dl class="dl-horizontal"> <dt>页眉</dt><dd><input ng-model="chartProps.header" class="form-control"/></dd> <dt>页尾</dt><dd><input ng-model="chartProps.footer" class="form-control"/></dd> <dt>X轴标题</dt><dd><input ng-model="chartProps.titleX" class="form-control"/></dd> <dt>Y轴标题</dt><dd><input ng-model="chartProps.titleY" class="form-control"/></dd> <dt></dt> <dd> <wj-menu value="chartProps.legendPosition" header="图例" > <wj-menu-item value="0">无</wj-menu-item> <wj-menu-item value="1">左</wj-menu-item> <wj-menu-item value="2">上</wj-menu-item> <wj-menu-item value="3">右</wj-menu-item> <wj-menu-item value="4">下</wj-menu-item> </wj-menu> </dd> </dl>
// add chart properties to scope $scope.chartProps = { chartType: wijmo.chart.ChartType.Column, legendPosition: wijmo.chart.Position.Right, stacking: wijmo.chart.Stacking.None, rotated: false, header: 'Sample Chart', footer: 'copyright (c) ComponentOne', titleX: 'country', titleY: 'amount' };
.wj-flexchart .wj-title { font-weight: bold; } .wj-flexchart .wj-header .wj-title { font-size: 18pt; fill: #80044d; } .wj-flexchart .wj-footer .wj-title { fill: #80044d; } .wj-flexchart .wj-axis-x .wj-title, .wj-flexchart .wj-axis-y .wj-title { font-style: italic; }

结果:

页眉
页尾
X轴标题
Y轴标题

工具提示

FlexChart对工具提示有内置的支持。 默认情况下,当用户触摸或者悬停鼠标到一个数据点时,控件会显示工具提示。

工具提示的内容是使用一个可能包含下列参数的模板生成:

默认情况下,tooltip模板被设为<b>{seriesName}</b><br/>{x} {y},你可以在上面的图表看到它是如何工作的。 在这个示例中,我们设tooltip模板为<b>{seriesName}</b> <img src='resources/{x}.png'/><br/>{y}, 它使用国家的国旗代替了国家的名字。

你可以通过设置模板为空字符串来禁用图表tooltips。

<wj-flex-chart items-source="data" tooltip-content="<img src='resources/{x}.png'/> <b>{seriesName}</b><br/>{y}" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"></wj-flex-chart-series> </wj-flex-chart>

结果:

样式系列

FlexChart为每个基于默认调色板的系列自动选取颜色,你可以通过设置palette属性来重写它。 但你也可以重写默认的属性,通过设置任意一个系列的style属性为一个对象, 它制定了SVG样式属性,包括fill, stroke, strokeThickness等等。

Series.style属性对在Wijmo中通过CSS设置样式的一般规则来说,是一个例外。 这个例外反映一个事实,许多图表有动态系列,这是不可能提前布置样式的。 比如,一个股票图表可能会展示用户在运行程序时才选中的系列。

这个示例中的图表使用了stylesymbolStyle属性来为每个系列选择样式属性:

<wj-flex-chart items-source="data" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales" ng-attr-style="{fill:'green', stroke:'darkgreen', 'stroke-width': '1'}"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses" ng-attr-style="{fill:'red', stroke:'darkred', 'stroke-width': '1'}"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads" chart-type="'LineSymbols'" ng-attr-style="{ stroke:'orange', 'stroke-width': '5'}" ng-attr-symbol-style="{fill:'gold', stroke:'gold' }"></wj-flex-chart-series> </wj-flex-chart>

结果:

自定义轴

使用axis属性来自定义图表的坐标轴,包括范围(最小值和最大值)、便签格式、刻度间隔和网格线。

Axis类有布尔属性,允许你打开或关闭功能(如axisLine, labels, majorTickMarksmajorGrid)。 你可以使用CSS来设置这些已经打开的功能的样式。

<wj-flex-chart items-source="data" binding-x="country"> <wj-flex-chart-axis wj-property="axisX" axis-line="true" major-grid="true"> </wj-flex-chart-axis> <wj-flex-chart-axis wj-property="axisY" format="c0" max="10000" major-unit="2000" axis-line="true" major-grid="true"> </wj-flex-chart-axis> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> </wj-flex-chart>

结果:

主题

FlexChart的外观是在CSS中定义的。除了默认的主题,我们有十几个专业设计的主题。 它们自定义了所有Wijmo控件的外观来达到一致的,有吸引力的效果。

为了自定义图表的外观,检查你想要提供样式的元素并创建一些CSS规则来应用到这些元素中。

例如,如果你在IE或者谷歌浏览器上右击X轴上的一个标签,你会发现它是一个拥有”wj-label”类的元素, 它被包含在拥有”wj-flexchart”类的顶层控件元素中。这个示例中第一条CSS规则使用这条信息来自定义X标签。 规则选择器添加了额外的要求,父类元素必须拥有"wj-flexchart"类"custom-flex-chart"类。 如果没有的话,这个规则会用于这个页面所有的图表。

<wj-flex-chart class="custom-flex-chart" items-source="data" binding-x="country"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"></wj-flex-chart-series> </wj-flex-chart>
/* custom chart theme */ .custom-flex-chart.wj-flexchart .wj-axis-x .wj-label { font-family: Courier New, Courier, monospace; font-weight: bold; } .custom-flex-chart.wj-flexchart .wj-legend .wj-label { font-family: Courier New, Courier, monospace; font-weight: bold; } .custom-flex-chart.wj-flexchart .wj-legend > rect { fill: #f8f8f8; stroke: #c0c0c0; } .custom-flex-chart.wj-flexchart .wj-plot-area > rect { fill: #f8f8f8; stroke: #c0c0c0; }

结果:

选择模式

FlexChart允许你通过单击或者触摸选择系列或数据点。使用selectionMode属性来指定是否允许选择系列, 是否选择数据点或者无法选择(选择默认是关闭的)

设置selectionMode属性为Series或者Point会导致用户在单击鼠标的时候, FlexChart自动更新Selection属性, 并且将"wj-state-selected"类应用到选中的图表元素中。

Selection属性返回当前选中的系列。要得到当前选中的数据点, 得到当前选定的项并在选中的系列中使用Series.collectionView.currentItem属性,正如示例所示。

<wj-flex-chart items-source="data" binding-x="country" tooltip-content="" chart-type="{{chartProps.chartType}}" selection-mode="{{chartProps.selectionMode}}" selection="chartProps.selection"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"></wj-flex-chart-series> </wj-flex-chart> <div ng-hide="chartProps.selectionMode == 0 || chartProps.selection == null"> <h4> Current Selection</h4> <p> Series: <b>{​{chartProps.selection.name}}</b></p> <dl class="dl-horizontal" ng-hide="chartProps.selectionMode != 2 || chartProps.selection.collectionView.currentItem == null"> <dt>Country</dt><dd>{​{chartProps.selection.collectionView.currentItem.country}}</dd> <dt>Sales</dt><dd>{​{chartProps.selection.collectionView.currentItem.sales | number:2}}</dd> <dt>Expenses</dt><dd>{​{chartProps.selection.collectionView.currentItem.expenses | number:2}}</dd> <dt>Downloads</dt><dd>{​{chartProps.selection.collectionView.currentItem.downloads | number:0}}</dd> </dl> </div>
// add chart properties to scope $scope.chartProps = { chartType: wijmo.chart.ChartType.Column, stacking: wijmo.chart.Stacking.None, legendPosition: wijmo.chart.Position.Right, rotated: false, header: 'Sample Chart', footer: 'copyright (c) ComponentOne', titleX: 'country', titleY: 'amount', selectionMode: wijmo.chart.SelectionMode.Series, selection: null };

结果:

None Series Point Column Bar Scatter Line LineSymbols Area Spline SplineSymbols SplineArea

当前选择

Series: {{chartProps.selection.name}}

Country
{{chartProps.selection.collectionView.currentItem.country}}
Sales
{{chartProps.selection.collectionView.currentItem.sales | number:2}}
Expenses
{{chartProps.selection.collectionView.currentItem.expenses | number:2}}
Downloads
{{chartProps.selection.collectionView.currentItem.downloads | number:0}}

切换系列

Series类有一个visibility属性,让你决定一个系列是否应该展现在图表和图例中, 或者只在图例中,或者完全隐藏。

这个示例演示你应该如何使用visibility属性来通过两种方法切换系列的可见性:

  1. 单击图例入口:
    图表指令会设置图表的legendToggle属性为真, 当它的图例入口被单击的时候就会切换一个系列的visibility属性
  2. 使用checkbox:
    这个页面使用Angular指令来将输入控件和每个系列的visibility属性绑定。
<wj-flex-chart items-source="data" legend-toggle="true" control="toggleChart"> <wj-flex-chart-series name="Sales" binding="sales"></wj-flex-chart-series> <wj-flex-chart-series name="Expenses" binding="expenses"></wj-flex-chart-series> <wj-flex-chart-series name="Downloads" binding="downloads"></wj-flex-chart-series> </wj-flex-chart> Sales <input type="checkbox" ng-model="toggleChart.series[0].visibility" ng-true-value="0" ng-false-value="2" ng-checked="true"/><br /> Expenses <input type="checkbox" ng-model="toggleChart.series[1].visibility" ng-true-value="0" ng-false-value="2" ng-checked="true"/><br /> Downloads <input type="checkbox" ng-model="toggleChart.series[2].visibility" ng-true-value="0" ng-false-value="2" ng-checked="true"/>
// toggle series visibility when user clicks on the legend // (note: this code is in the chart directive) control.hostElement.addEventListener('click', function (e) { if (scope.seriesToggle == true) { var ht = control.hitTest(e); if (ht && ht.chartElement == wijmo.chart.ChartElement.Legend && ht.series) { if (ht.series.visibility == wijmo.chart.SeriesVisibility.Legend) { ht.series.visibility = wijmo.chart.SeriesVisibility.Visible; } else { ht.series.visibility = wijmo.chart.SeriesVisibility.Legend; } } } });

结果:

Sales
Expenses
Downloads

动态图表

FlexChart内部使用了ICollectionView,因此你对数据源做的任何更改都会自动反映在图表中。

在这个示例中,我们使用一个计时器来向数据源中增加项目,丢弃旧项目以保持总数为200。 结果就是一个动态的图表,当新数据到来时图表向右滚动。

<wj-flex-chart items-source="trafficData" chart-type="Area" stacking="Stacked" binding-x="time"> <wj-flex-chart-axis wj-property="axisX" format="mm:ss"></wj-flex-chart-axis> <wj-flex-chart-series name="Trucks" binding="trucks"></wj-flex-chart-series> <wj-flex-chart-series name="Ships" binding="ships"></wj-flex-chart-series> <wj-flex-chart-series name="Planes" binding="planes"></wj-flex-chart-series> </wj-flex-chart> <div class="btn-group"> <button type="button" class="btn btn-default" ng-click="setInterval(200)">慢速</button> <button type="button" class="btn btn-default" ng-click="setInterval(100)">中等</button> <button type="button" class="btn btn-default" ng-click="setInterval(50)">快速</button> <button type="button" class="btn btn-default" ng-click="setInterval(0)">停止</button> </div>
// dynamic data var toAddData; $scope.trafficData = new wijmo.collections.ObservableArray(); $scope.setInterval = function (interval) { if (toAddData) { clearTimeout(toAddData); toAddData = null; } $scope.interval = interval; if (interval) { toAddData = setTimeout(addTrafficItem); } }; $scope.setInterval(500); function addTrafficItem() { // add random data, limit array length ... // keep adding ... }

结果:

更新速度