Dragonchart 入门——基于HTML5的开源信息图绘制组件
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组成。这种模式有几个优点:
- 可重用性:不同类型的图表所需的许多相同函数都写在core.js中,实现了代码重用;
- 独立性:特定功能写在各自的type.js文件中,互不干扰。
- 可扩展性:我可以以最小的风险添加新的图表类型,而不会破坏旧类型的结构。
- 可维护性:当我需要修改代码时,可以快速找到目标代码。
对于Dragonchart这样的组件来说,选项的布局非常重要。如果太简单,用户就无法详细控制图表,也就无法绘制出他们想要的效果;如果太复杂,用户则懒得去了解所有选项,这会让他们缺乏深入了解组件的动力,甚至有时会放弃。基于这种情况,我设计了最多两级选项。通用选项定义在dragonchart.core.js中,特定选项定义在每个dragonchart.[type].js文件中。
以下是Dragonchart源代码的列表。除了core.js和27个[type].js文件外,还有两个额外的js文件:all.delay.js和skins.js,我稍后会介绍它们。

Dragonchart 图形结构

可以看到,这张图由几个部分组成,包括标题、副标题、图例、刻度、提示、坐标轴、坐标轴标题、页脚、注释,当然还有核心图形元素。
有些部分是必需的,有些则不是。核心图形元素当然是必需的。在绘制坐标轴图表时,例如柱状图、直方图、折线图、面积图等,标签轴和值轴是必需的。在绘制非坐标轴图表时,例如饼图、环形图、雷达图等,坐标轴则不是必需的。
除了Dragonchart原生支持的上述部分,您还可以使用Dragonchart支持的自定义绘制功能在图形上绘制额外的元素,理论上您可以获得任何您期望的图形。
版本更新
Dragonchart到目前为止已经有两个版本更新。
从Dragonchart 1.0到Dragonchart 1.1,除了修复一些bug之外,最重要的变化是增加了六种图表类型。原始类型包括:饼图、环形图、多环图、极坐标图、雷达图、柱状图、堆叠柱状图、直方图、堆叠直方图、折线图、散点图和面积图。Dragonchart 1.1中新增的类型包括:范围柱状图、范围直方图、范围面积图、嵌套饼图、队列柱状图、队列直方图。得益于“核心+类型”模式,我花费很少的时间和精力就完成了这个版本的更新。
从Dragonchart 1.1到Dragonchart 1.2的版本更新对我来说就像一场噩梦,至少在早期是这样。这次版本更新有三大改进:
- 新增九种3D图表类型:我发现3D比2D更酷,所以我决定为Dragonchart添加3D类型。起初,我估计只需要一点点精力就可以完成,但很快我就发现自己错了。我不得不修改core.js中的一些核心函数,并添加一些与3D相关的选项。
- 支持插件:插件是同一张图表中的另一个图表。例如,当您需要在折线图中添加一个额外的饼图时,您需要将饼图插件添加到折线图中。老实说,在我完成Dragonchart 1.0之前,我曾经考虑过支持插件,但由于基本结构已经建立,我懒得去破坏和重建它。唉,我尝到了不好的后果。最后,我花了一周时间仔细重建了整个Dragonchart,并成功支持了插件。
- 添加图例控制:Highcharts有一个很棒的功能:通过点击图例来控制某些数据的可见性。得益于重构以支持插件,添加这个重要功能变得非常容易。
通过这些版本更新,我得到了一些结论:
虽然并非所有方面都能在设计阶段考虑到,但我们应该仔细设计,为未来的变化做好准备。我知道说起来容易做起来难,但我们确实需要引起注意。
- 如果您希望您的软件完美,您绝不能放松。有时我们可能会觉得我们的软件有点缺陷,然后想:小问题就让它过去吧。一开始我也是这么想的,但当我发现Dragonchart与其他类似的图表绘制工具相比价值不高时,我最终激励自己对编码“偏执”,并为Dragonchart添加了一些有用的功能,如自定义绘制、皮肤、插件等。现在我认为,正是这种追求完美的严谨态度成就了史蒂夫·乔布斯的成功,而非他其他优秀的品质。
- 多设计,少编码。盲目编码会浪费您的时间和精力,良好的设计将减少您的工作量,同时增强您软件的功能。
DChart对象内部属性、事件和函数的简单介绍
属性
DrawFigures
:此对象包含绘制自定义图形的函数,例如createText
、createLine
等。用户可以调用这些函数来绘制额外的图形元素,以满足特殊需求。GraphType
:此属性记录当前的图形类型,例如‘Pie’、‘Radar’等。ID
:此属性保存一个ID字符串,用于标识当前使用的DChart
。
:此属性保存语言设置。Language
Canvas
:此对象是创建在父级div
DOM内部的DOM对象。Coordinates
:此对象收集了绘制的每个图形元素的坐标信息,例如大小、位置等。ctx
:通过canvas.getContext('2d')
获取的对象innerData
:此对象保存用户传入的数据(如果用户使用纯数组数据,则innerData
保存DChart
从纯数组数据转换而来的普通对象数据)。innerOptions
:此对象保存用户传入的选项。shapes
:此数组保存绘制图形过程中的临时图形。它用于重新绘制部分或全部图形、获取坐标信息、响应鼠标事件等,具有重要用途。_configs
:顾名思义,configs在dchart
对象内部使用。
事件
onStart
:内置事件,在DChart
“开始工作”时执行。onBeforeAnimation
:内置事件,在DChart
开始动画时执行。onAnimation
:内置事件,在动画进行时执行。向函数传递一个参数,显示动画完成的百分比。onFinish
:内置事件,在DChart
完成当前绘制任务时执行。
函数
AddPlugin
:将插件添加到dragonchart。ChangeLanguage
:更改内部语言。ClearBackGround
:清除画布上的所有元素,包括画布草图、显示提示的span、已保存的图形等。ClearPlugin
:清除之前添加的所有插件。RemovePlugin
:与ClearPlugin
不同,此函数只移除一个插件。Draw
:核心函数,用于开始绘制图形。此函数有两个参数:数据和选项。用户可以只传递其中一个,或者都不传递,前提是:当不传递数据时,必须先调用SetData
函数;当不传递选项时,必须先调用SetOptions
函数。GetCoordinate
:获取图形元素的实时坐标信息。参数location是定位用户所需坐标的“路径字符串”。“.”用于表示子项,例如“canvas.height
”代表画布的高度。用户可以使用“.[index]
”来获取数组格式的坐标信息,例如,“pie.outerlabels.3.left
”代表饼图半圆的第四个外部标签的左边位置。Initial
:重新初始化画布元素。操作包括删除旧的画布元素(如果存在)、删除DCharts中的旧样式、添加新样式、计算画布的基本坐标信息、添加新的画布元素、初始化配置、清除画布等。总之,此函数用于初始化一个新画布以绘制图形。SavePic
:导出画布的图片(某些浏览器不支持)。参数是文件名和图片类型,例如png、bmp、gif。SetBasicOptions
:更改DChart
的基本配置。此函数可以更改画布大小,因此调用此函数时,会在内部调用Initial
。SetData
:加载数据。此函数专门用于加载数据,独立于Draw
函数,效果与在Draw
函数中加载数据一致。SetDefaultOptions
:恢复默认选项,包括通用选项和特定选项。SetOptions
:加载选项,与SetData
类似,独立于Draw
函数。SetSkin
:为DChart
设置皮肤。您可以使用内置皮肤或自己的自定义皮肤。
Dragonchart 的特点
整体特点
- 纯HTML5和JavaScript,跨平台,不依赖任何框架。您可以在PC、移动设备或任何支持HTML5和JavaScript的终端上使用它。
- 支持多种常用绘图类型。Dragonchart目前支持27种图形类型(包括2D和3D),并且计划在未来支持更多类型。
- 支持插件图形。您可以在一张图中组合多种类型的图形。
- 支持核心代码内的语言设置。语言设置用于错误消息。如果您使用Dragonchart的方式不正确,Dragonchart会告诉您哪里出了问题。
- 支持动画。有时您可能想看到绘制图形的动画进度,因为动画能使图形更酷。
- 支持皮肤设置和自定义皮肤。Dragonchart有几种内置皮肤,您只需调用
dchart_obj.SetSkin
即可应用,从而无需逐个设置选项即可获得多彩的图形。当然,您也可以根据个人喜好设计自己的皮肤。 - 支持多种图形的3D绘制。您可能会发现3D比2D更酷,我也是如此。因此,Dragonchart支持9种3D图形类型,例如饼图、环形图、直方图。
- 记录元素的位置、大小等信息以便查询。Dragonchart记录了图形中重要元素的最终坐标信息,例如标题的大小、图例的位置等。您可以在
dchart_obj
.coordinates中获取所有记录的坐标信息。 - 支持自定义绘制。除了构建图形的常规元素外,您可能需要添加额外的元素(例如文本、线条、圆形等)来为图形提供更多信息。Dragonchart记录的实时坐标信息可能会对您大有帮助。
- 支持导出图片。您只需调用
dchart_obj.SavePic
即可导出图片,但目前仅支持Firefox和部分Chrome版本。 - 延迟加载。Dragonchart由dragonchart.core.js和许多dragon.[types].js组成,当您需要绘制饼图时,需要引用core.js和pie.js。当您需要使用插件绘制图形时,这种情况会变得相当繁琐。因此,dragonchart.all.delay.js应运而生。您只需引用dragon.core.js和dragonchart.all.delay.js,当需要饼图时,Dragonchart会加载一次pie.js;当需要柱状图时,会加载一次bar.js。这样使用起来是不是更方便了?
选项特点
- 最多两级选项,避免了多级带来的使用不便。
- 选项设置的多级优先级(以
fontcolor
为例,“数据设置”>“选项设置”>“皮肤设置”>“默认设置”); - 检查传入的选项,如果某个选项不正确,则会抛出带有详细信息的错误。
数据特点
- 使用JSON格式的数据源。您知道这个特性对于Web开发者来说似乎微不足道。您可以忽略它。
- 轴支持数字、百分比(自动计算)、日期时间(天的顺序)、时间(分钟的顺序)四种不同的数据类型。
- 图形中的某些特性直接在数据中设置(性能上比通过选项设置具有更高的优先级)。
- 支持纯数组数据源,使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。
请注意
- dragonchart.all.delay.js中不包含所有图形的实际代码,它只是使用了延迟加载函数,所以所有的[type.js]文件必须与[all.js]文件放在同一个目录。
- 如果需要设置皮肤,请确保引用了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. 准备数据源
数据源有三个功能:
- 确定图形元素的大小、位置和其他基本信息
- 确定图形元素的颜色和外观信息
- 确定图形元素的交互、鼠标事件
以下是收集的样本数据,显示了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. 绘制图形
- 创建一个用于接收画布的
div
元素 - 准备数据源并设置选项
- 新建一个
DChart
对象 - 绘制
<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选项的详细说明。