65.9K
CodeProject 正在变化。 阅读更多。
Home

Dragonchart 入门——基于HTML5的开源信息图绘制组件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (16投票s)

2014年1月26日

CPOL

13分钟阅读

viewsIcon

26861

downloadIcon

415

Dragonchart 入门——基于HTML5的开源信息图绘制组件

Dragonchart 简介

Dragonchart 是一个基于HTML5 Canvas的开源信息图绘制组件。一般来说,图片比文字更能给人留下深刻印象,尤其是在展示某些数据时。想象一下,你是一位专注于IT行业的编辑,需要写一篇关于近期各PC制造商市场份额的文章。一方面,你当然需要在文章中写上几百字,比如‘联想占15.5%,戴尔占13.2%……’之类的话;另一方面,你还需要在文字旁配上一张图,比如饼图或柱状图,以加深读者对数据效果的印象。各行各业的人们都会产生大量数据,当需要向他人展示数据时,图表也就应运而生了。Dragonchart 就是这样一款绘制图表图片的工具。

在Dragonchart之前,已经有一些类似的绘制工具,例如jqplot、highcharts等。包括Dragonchart在内,这些Web绘图工具可以分为三类:一类是使用非HTML技术,如Flash、Silverlight;二类是使用向量标记语言,这种语言最初是为了在浏览器中绘制向量图片而设计的,例如VML(仅在Internet Explorer中支持良好)和SVG(W3C推荐的标准),highcharts就是一个很好的使用SVG的例子;三类是使用HTML5 Canvas元素,Dragonchart就属于这一类。

本文仅对Canvas元素做一个粗略的介绍,您可以自行搜索获取更详细的信息。正如其名,Canvas元素就像一块画布,而开发者则像画家。开发者使用JavaScript来操作DOM对象,因此JavaScript可以比作画笔。严格来说,通过调用canvas.getContext('2d')获取的ctx对象,比Canvas元素本身更像是一块画布。一旦获取了ctx对象,您就可以调用许多函数来在画布上绘制您想要的任何内容,例如直线、圆形,填充或描边。理论上,您可以使用这些函数绘制任何您想要的东西。顺便说一句,通过重新绘制画布的一部分或全部,您可以在画布上实现动画效果,因此您可以使用Canvas元素制作游戏。

我花费了近五个月的业余时间编写了Dragonchart并搭建了展示网站。Dragonchart目前支持27种图表类型(包括2D和3D)。您可以在文章顶部的CodeProject链接下载Dragonchart的源代码。

源代码结构

我参考了ligerUI(由一位聪明的开发者编写)的设计,将Dragonchart设计为[核心+类型]模式。顾名思义,Dragonchart由dragonchart.core.js和几个dragonchart.[type].js组成。这种模式有几个优点:

  1. 可重用性:不同类型的图表所需的许多相同函数都写在core.js中,实现了代码重用;
  2. 独立性:特定功能写在各自的type.js文件中,互不干扰。
  3. 可扩展性:我可以以最小的风险添加新的图表类型,而不会破坏旧类型的结构。
  4. 可维护性:当我需要修改代码时,可以快速找到目标代码。

对于Dragonchart这样的组件来说,选项的布局非常重要。如果太简单,用户就无法详细控制图表,也就无法绘制出他们想要的效果;如果太复杂,用户则懒得去了解所有选项,这会让他们缺乏深入了解组件的动力,甚至有时会放弃。基于这种情况,我设计了最多两级选项。通用选项定义在dragonchart.core.js中,特定选项定义在每个dragonchart.[type].js文件中。

以下是Dragonchart源代码的列表。除了core.js和27个[type].js文件外,还有两个额外的js文件:all.delay.jsskins.js,我稍后会介绍它们。

Dragonchart 图形结构

可以看到,这张图由几个部分组成,包括标题、副标题、图例、刻度、提示、坐标轴、坐标轴标题、页脚、注释,当然还有核心图形元素。

有些部分是必需的,有些则不是。核心图形元素当然是必需的。在绘制坐标轴图表时,例如柱状图、直方图、折线图、面积图等,标签轴和值轴是必需的。在绘制非坐标轴图表时,例如饼图、环形图、雷达图等,坐标轴则不是必需的。

除了Dragonchart原生支持的上述部分,您还可以使用Dragonchart支持的自定义绘制功能在图形上绘制额外的元素,理论上您可以获得任何您期望的图形。

版本更新

Dragonchart到目前为止已经有两个版本更新。

从Dragonchart 1.0到Dragonchart 1.1,除了修复一些bug之外,最重要的变化是增加了六种图表类型。原始类型包括:饼图、环形图、多环图、极坐标图、雷达图、柱状图、堆叠柱状图、直方图、堆叠直方图、折线图、散点图和面积图。Dragonchart 1.1中新增的类型包括:范围柱状图、范围直方图、范围面积图、嵌套饼图、队列柱状图、队列直方图。得益于“核心+类型”模式,我花费很少的时间和精力就完成了这个版本的更新。

从Dragonchart 1.1到Dragonchart 1.2的版本更新对我来说就像一场噩梦,至少在早期是这样。这次版本更新有三大改进:

  1. 新增九种3D图表类型:我发现3D比2D更酷,所以我决定为Dragonchart添加3D类型。起初,我估计只需要一点点精力就可以完成,但很快我就发现自己错了。我不得不修改core.js中的一些核心函数,并添加一些与3D相关的选项。
  2. 支持插件:插件是同一张图表中的另一个图表。例如,当您需要在折线图中添加一个额外的饼图时,您需要将饼图插件添加到折线图中。老实说,在我完成Dragonchart 1.0之前,我曾经考虑过支持插件,但由于基本结构已经建立,我懒得去破坏和重建它。唉,我尝到了不好的后果。最后,我花了一周时间仔细重建了整个Dragonchart,并成功支持了插件。
  3. 添加图例控制:Highcharts有一个很棒的功能:通过点击图例来控制某些数据的可见性。得益于重构以支持插件,添加这个重要功能变得非常容易。

通过这些版本更新,我得到了一些结论:

  1. 虽然并非所有方面都能在设计阶段考虑到,但我们应该仔细设计,为未来的变化做好准备。我知道说起来容易做起来难,但我们确实需要引起注意。

  2. 如果您希望您的软件完美,您绝不能放松。有时我们可能会觉得我们的软件有点缺陷,然后想:小问题就让它过去吧。一开始我也是这么想的,但当我发现Dragonchart与其他类似的图表绘制工具相比价值不高时,我最终激励自己对编码“偏执”,并为Dragonchart添加了一些有用的功能,如自定义绘制、皮肤、插件等。现在我认为,正是这种追求完美的严谨态度成就了史蒂夫·乔布斯的成功,而非他其他优秀的品质。
  3. 多设计,少编码。盲目编码会浪费您的时间和精力,良好的设计将减少您的工作量,同时增强您软件的功能。

DChart对象内部属性、事件和函数的简单介绍

属性

  1. DrawFigures:此对象包含绘制自定义图形的函数,例如createTextcreateLine等。用户可以调用这些函数来绘制额外的图形元素,以满足特殊需求。
  2. GraphType:此属性记录当前的图形类型,例如‘Pie’、‘Radar’等。
  3. ID:此属性保存一个ID字符串,用于标识当前使用的DChart
  4. Language:此属性保存语言设置。
  5. Canvas:此对象是创建在父级divDOM内部的DOM对象。
  6. Coordinates:此对象收集了绘制的每个图形元素的坐标信息,例如大小、位置等。
  7. ctx:通过canvas.getContext('2d')获取的对象
  8. innerData:此对象保存用户传入的数据(如果用户使用纯数组数据,则innerData保存DChart从纯数组数据转换而来的普通对象数据)。
  9. innerOptions:此对象保存用户传入的选项。
  10. shapes:此数组保存绘制图形过程中的临时图形。它用于重新绘制部分或全部图形、获取坐标信息、响应鼠标事件等,具有重要用途。
  11. _configs:顾名思义,configs在dchart对象内部使用。

事件

  1. onStart:内置事件,在DChart“开始工作”时执行。
  2. onBeforeAnimation:内置事件,在DChart开始动画时执行。
  3. onAnimation:内置事件,在动画进行时执行。向函数传递一个参数,显示动画完成的百分比。
  4. onFinish:内置事件,在DChart完成当前绘制任务时执行。

函数

  1. AddPlugin:将插件添加到dragonchart。
  2. ChangeLanguage:更改内部语言。
  3. ClearBackGround:清除画布上的所有元素,包括画布草图、显示提示的span、已保存的图形等。
  4. ClearPlugin:清除之前添加的所有插件。
  5. RemovePlugin:与ClearPlugin不同,此函数只移除一个插件。
  6. Draw:核心函数,用于开始绘制图形。此函数有两个参数:数据和选项。用户可以只传递其中一个,或者都不传递,前提是:当不传递数据时,必须先调用SetData函数;当不传递选项时,必须先调用SetOptions函数。
  7. GetCoordinate:获取图形元素的实时坐标信息。参数location是定位用户所需坐标的“路径字符串”。“.”用于表示子项,例如“canvas.height”代表画布的高度。用户可以使用“.[index]”来获取数组格式的坐标信息,例如,“pie.outerlabels.3.left”代表饼图半圆的第四个外部标签的左边位置。
  8. Initial:重新初始化画布元素。操作包括删除旧的画布元素(如果存在)、删除DCharts中的旧样式、添加新样式、计算画布的基本坐标信息、添加新的画布元素、初始化配置、清除画布等。总之,此函数用于初始化一个新画布以绘制图形。
  9. SavePic:导出画布的图片(某些浏览器不支持)。参数是文件名和图片类型,例如png、bmp、gif。
  10. SetBasicOptions:更改DChart的基本配置。此函数可以更改画布大小,因此调用此函数时,会在内部调用Initial
  11. SetData:加载数据。此函数专门用于加载数据,独立于Draw函数,效果与在Draw函数中加载数据一致。
  12. SetDefaultOptions:恢复默认选项,包括通用选项和特定选项。
  13. SetOptions:加载选项,与SetData类似,独立于Draw函数。
  14. SetSkin:为DChart设置皮肤。您可以使用内置皮肤或自己的自定义皮肤。

Dragonchart 的特点

整体特点

  1. 纯HTML5和JavaScript,跨平台,不依赖任何框架。您可以在PC、移动设备或任何支持HTML5和JavaScript的终端上使用它。
  2. 支持多种常用绘图类型。Dragonchart目前支持27种图形类型(包括2D和3D),并且计划在未来支持更多类型。
  3. 支持插件图形。您可以在一张图中组合多种类型的图形。
  4. 支持核心代码内的语言设置。语言设置用于错误消息。如果您使用Dragonchart的方式不正确,Dragonchart会告诉您哪里出了问题。
  5. 支持动画。有时您可能想看到绘制图形的动画进度,因为动画能使图形更酷。
  6. 支持皮肤设置和自定义皮肤。Dragonchart有几种内置皮肤,您只需调用dchart_obj.SetSkin即可应用,从而无需逐个设置选项即可获得多彩的图形。当然,您也可以根据个人喜好设计自己的皮肤。
  7. 支持多种图形的3D绘制。您可能会发现3D比2D更酷,我也是如此。因此,Dragonchart支持9种3D图形类型,例如饼图、环形图、直方图。
  8. 记录元素的位置、大小等信息以便查询。Dragonchart记录了图形中重要元素的最终坐标信息,例如标题的大小、图例的位置等。您可以在dchart_obj.coordinates中获取所有记录的坐标信息。
  9. 支持自定义绘制。除了构建图形的常规元素外,您可能需要添加额外的元素(例如文本、线条、圆形等)来为图形提供更多信息。Dragonchart记录的实时坐标信息可能会对您大有帮助。
  10. 支持导出图片。您只需调用dchart_obj.SavePic即可导出图片,但目前仅支持Firefox和部分Chrome版本。
  11. 延迟加载。Dragonchart由dragonchart.core.js和许多dragon.[types].js组成,当您需要绘制饼图时,需要引用core.jspie.js。当您需要使用插件绘制图形时,这种情况会变得相当繁琐。因此,dragonchart.all.delay.js应运而生。您只需引用dragon.core.jsdragonchart.all.delay.js,当需要饼图时,Dragonchart会加载一次pie.js;当需要柱状图时,会加载一次bar.js。这样使用起来是不是更方便了?

选项特点

  1. 最多两级选项,避免了多级带来的使用不便。
  2. 选项设置的多级优先级(以fontcolor为例,“数据设置”>“选项设置”>“皮肤设置”>“默认设置”);
  3. 检查传入的选项,如果某个选项不正确,则会抛出带有详细信息的错误。

数据特点

  1. 使用JSON格式的数据源。您知道这个特性对于Web开发者来说似乎微不足道。您可以忽略它。
  2. 轴支持数字、百分比(自动计算)、日期时间(天的顺序)、时间(分钟的顺序)四种不同的数据类型。
  3. 图形中的某些特性直接在数据中设置(性能上比通过选项设置具有更高的优先级)。
  4. 支持纯数组数据源,使JSON数据结构的来源更简单清晰。普通数据是包含value、text等属性的对象,此函数支持数组作为数据,但要求按文本(必需)、值(必需)、子项、颜色、点击、鼠标移入、鼠标移出顺序排列。例如:[['Shanghai', 23.47], ['Beijing',20.69], ['New York',19.88,'#ffffff',function(){alert('click!');}]]

一个简单的演示,一步一步完成

1. 引用DChart

您可以只引用dragonchart.core.(min.)js + dragonchart.all.delay.(min.)js;或者引用dragonchart.core.(min.)js以及根据绘图类型所需的特定js,例如现在我需要绘制一个饼图,那么我还需要dragonchart.pie.(min.)js

请注意

  1. dragonchart.all.delay.js中不包含所有图形的实际代码,它只是使用了延迟加载函数,所以所有的[type.js]文件必须与[all.js]文件放在同一个目录。
  2. 如果需要设置皮肤,请确保引用了dragonchart.skins.js
<script type="text/javascript" src="dragonchart 1.2/dragonchart.core.js"></script>
<script type="text/javascript" src="dragonchart 1.2/dragonchart.all.delay.js"></script>
<script type="text/javascript" src="dragonchart 1.2/dragonchart.skins.js"></script>  

或者:

<script type="text/javascript" src="dragonchart 1.2/dragonchart.core.js"></script> 
<script type="text/javascript" src="dragonchart 1.2/dragonchart.pie.js"></script> 
<script type="text/javascript" src="dragonchart 1.2/dragonchart.skins.js"></script>

2. 准备数据源

数据源有三个功能:

  1. 确定图形元素的大小、位置和其他基本信息
  2. 确定图形元素的颜色和外观信息
  3. 确定图形元素的交互、鼠标事件

以下是收集的样本数据,显示了Firefox、Internet Explorer、Chrome、Safari、Opera等五大浏览器份额。

var data = [{
    //define text(label) of a single element
    text: "Firefox",
    //define value of element
    value: 45,
    //define click event function for this element    
    click: function (data, evt) { alert('This is Firefox, value is ' + data.value); }
},{
    text: "IE",
    value: 26.8,
    //Setting up feature through data has a higher priority than through options.
    extended: true
},{
    text: "Chrome",
    value: 12.8,
    //define click event function for this element
    click: function (data, e) { alert('Hi! This is Chrome explorer data!'); }
},{
    text: "Safari",
    value: 8.5
},{
    text: "Opera",
    value: 6.2
},{
    text: "Others",
    value: 0.7
}];

3. 设置选项

选项决定了图形的每个部分应该如何绘制,例如标题、副标题、图例、坐标轴等。

以下设置了标题和副标题,默认情况下,图例是显示的,最终渲染的图形包括标题、副标题、图例和核心图形。

var options = {
    //Define title content
    title: { content: 'Top 5 Browsers from 1 to 29 Feb 2012' },
    //Define subtitle content
    subTitle: { content: 'Let see which brower shares the most.' }
}; 

4. 选择皮肤

皮肤设置不是一个必要的步骤。为了尽可能多地展示DChart的使用,本示例使用了简单的“BlackAndWhite”皮肤。

顺便说一句,除了dragonchart.skins.js中定义的现有皮肤外,DChart还支持自定义皮肤。

5. 绘制图形

  1. 创建一个用于接收画布的div元素
  2. 准备数据源并设置选项
  3. 新建一个DChart对象
  4. 绘制
<div id="divCanvas" style="width: 800px; height: 400px;"></div> 
//Create a DChart object according to div's id and language needed
window.dchart = new DChart.Pie('divCanvas', 'CN');
//Use "BlackAndWhite" skin
dchart.SetSkin('BlackAndWhite');
//Use options, you can directly call dchart.Draw(data, options) to use options and data at one time.
dchart.SetOptions(options);
//Start drawing. You can also call dchart.SetData(data) first, then call dchart.Draw() to achieve the same goal.
dchart.Draw(data);
//Below is a very simple way:
(new DChart.Pie('divCanvas', 'CN')).SetSkin('BlackAndWhite').Draw(data, options); 

6. 检查结果

结束语

本文仅对Dragonchart进行了简单的介绍,如果您想了解更多关于Dragonchart的信息,请点击此处访问我的网站。我网站上的“DChart在线编辑和演示中心”(点击此处)为您提供了实时设计的图形绘制示例。“DChart自定义皮肤”(点击此处)允许您自定义自己的皮肤。您可以在“文档”页面获取Dragonchart选项的详细说明。

© . All rights reserved.