使用Dojo Toolkit来创建移动图表应用
原作者:
来源Charting for mobile with the Dojo Toolkit
译者Elaine.Ye
(译者注:由于yeeyan编辑器对文章中的标签做解析的原因,我在每个标签的空格,比如说,左尖括号<+script+右尖括号>,我会写成< script>,以便其能够在文章中正确显示,不便之处敬请谅解。)
引言
在本文中,我们学习如何使用Dojo Toolkit的图表框架来创建一些运行在移动设备上的很吸引人的图表应用,学习如何在Dojo移动应用的内部实例化和配置图表组件,以及如何在组件上启用触摸交互,以达成与移动设备的更好整合。我们还会探讨图表应用的的一些可改进加载和渲染速度的高级可选做法。
你还可以下载本文的源代码。
创建一个Dojo Mobile图表应用
在使用Dojo来构建移动应用时,这里的建议是依赖dojox.mobile包来完成。这是一个相对较薄的Dojo层,其提供了一组面向移动的轻量级的部件、一个解析器和一个过渡框架。考虑到移动应用的这些功能的重要性,大多数的移动Dojo图表应用都有可能会使用这一框架。
在dojox.mobile应用的上下文中实例化图表的最简单方式是依赖解析并把图表代码置于dojox.mobile部件标记的内部(类似于你在普通的Dijit桌面应用中会采用的做法),首先你需要一个定义了应用标记的HTML文件,接着是一个HTML引用的JavaScript源文件,该文件包含了应用的JavaScript逻辑。
本文中的例子给你展示了如何构建一个使用柱状图来显示销售数据的简单应用,该柱状图以月为单位,覆盖的时间阶段为三年。清单1中的代码被用来创建一个HTML文件。
清单1. 最初的移动图表应用的HTML文件
< !DOCTYPE HTML>
< html>
< head>
< title>Dojo Toolkit Mobile Charting< /title>
< meta name="viewport" content="width=device-width,initial-scale=1,
maximum-scale=1,minimum-scale=1,user-scalable=no"/>
< meta name="apple-mobile-web-app-capable" content="yes" />
< link rel="stylesheet" type="text/css"
href="../../../dojo_current/dojox/mobile/themes/iphone/iphone.css">
< script type="text/javascript" src="../../../dojo_current/dojo/dojo.js" kesrc="../../../dojo_current/dojo/dojo.js"
data-dojo-config="parseOnLoad: true">< /script>
< script type="text/javascript" src="src_01.js" kesrc="src_01.js" charset="utf-8">< /script>
< /head>
< body>
< div id="view1" data-dojo-type="dojox.mobile.View">
< h1 id="head1" data-dojo-type="dojox.mobile.Heading">Chart View< /h1>
< div data-dojo-type="dojox.mobile.RoundRect">
< button id="b1" data-dojo-type="dojox.mobile.Button"
class="mblBlueButton">Zoom< /button>
< button id="b2" data-dojo-type="dojox.mobile.Button"
class="mblBlueButton">Unzoom< /button>
< div data-dojo-type="dojox.charting.widget.Chart" id="chart"
style="width: 100%; height: 180px;">
< div class="plot" name="grid" type="Grid"
vMinorLines="true">< /div>
< div class="axis" name="x"
fixUpper="minor"
majorTickStep="1"
minorTicks="false">< /div>
< div class="axis" name="y" vertical="true" min="0">< /div>
< div class="plot" name="plot" type="Columns" >< /div>
< div class="series" name="data" plot="plot"
data="20, 32, 32, 45, 37, 28, 24, 48, 44, 21, 32, 33,
32, 34, 44, 32, 39, 43, 44, 46, 36, 41, 25, 27,
28, 45, 46, 33, 34, 35, 29, 44, 48, 48, 49, 43">< /div>
< /div>
< /div>
< /div>
< /body>
< /html>
清单1中的代码在Dojo的数据类型属性中引用了dojox.mobile和dojox.charting的类。为了正确地解析和实例化这一标记,JavaScript源文件必须要导入相应的模块,如清单2所示。
清单2. 最初的移动图表应用的JavaScript源文件
require(["dojo", "dojox/mobile", "dojox/mobile/parser",
"dojox/mobile/Button", "dojox/charting/widget/Chart",
"dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Grid"]);
本文中的例子基于最近介绍过的用于管理Dojo应用依赖的AMD语法(请参阅参考资料以了解更多关于AMD的内容。)如果你不不想切换到新格式上的话,一个有着向后兼容性的类似应用可以使用已被取代的dojo.require这一依赖格式来构建。
如果运行相应应用的话,你应该会得到图1所示的结果。
图1. 一个移动图表应用
图1中的图表仅仅是一个静态非交互式的图表,数据是来自定义在标记中的series的data属性的硬编码数据。在进一步深入之前,应用需要做一些小的调整。
到目前为止,该应用是专为Webkit移动和桌面浏览器定做的,如果你希望应用最好还能运行在诸如Firefox一类的桌面浏览器上的话,你可以更新依赖列表,加入dojox/mobile/compat模块,如清单3所示。该例子使用了dojo/has这一AMD插件,只有当应用没有运行在Webkit浏览器上,需要用到兼容性模块时,才会包含该模块。
清单3. 加入对非Webkit浏览器的支持
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojox/mobile", "dojox/mobile/parser",
"dojo/has!webKit?:dojox/mobile/compat",
"dojox/mobile/Button", "dojox/charting/widget/Chart",
"dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Grid"]);
下一步是使用外部的数据源而不是应用中的硬编码数据来给显示的图表提供数据,你可以使用Dojo Charting和Dojo Core的数据存储API来实现这一点。
dojo.data和dojox.data包中的一些类允许你从各种数据源中加载数据,并把这些数据源和Dojo组件连接起来。例如。假设你在服务器端有着清单4中的这些JSON数据,你希望加载它。
清单4. JSON数据示例
{
"items":
[
{"value": 0}, {"value": 32}, {"value": 32}, {"value": 45}, {"value": 37}, {"value": 28},
{"value": 24}, {"value": 48}, {"value": 44}, {"value": 21}, {"value": 32},
{"value": 33}, {"value": 32}, {"value": 34}, {"value": 44}, {"value": 32},
{"value": 39}, {"value": 43}, {"value": 44}, {"value": 46}, {"value": 36},
{"value": 41}, {"value": 25}, {"value": 27}, {"value": 28}, {"value": 45},
{"value": 46}, {"value": 33}, {"value": 34}, {"value": 35}, {"value": 29},
{"value": 44}, {"value": 48}, {"value": 48}, {"value": 49}, {"value": 43}
]
}
JSON数据可通过dojo.data.ItemFileReadStore实例来加载,若要使用图表来处置数据的话,你要把dojo.data实例和Series对象连接起来,该对象负责使用来自存储中的数据项填充图表。
首先你要修改HTML中的series的声明,把硬编码数据输入改成引用一个名为“store”的数据存储,把清单6中的Series的定义改成包含store="store",如清单7所示。
清单6. 之前的Seires定义
< div class="series" name="data" plot="plot"
data="20, 32, 32, 45, 37, 28, 24, 48, 44, 21, 32, 33,
32, 34, 44, 32, 39, 43, 44, 46, 36, 41, 25, 27,
28, 45, 46, 33, 34, 35, 29, 44, 48, 48, 49, 43">< /div>
清单7. 之前的Series定义,包含了store
< div class="series" name="data" store="store" plot="plot">< /div>
在这同一HTML文件中你可以使用清单8中的标记来定义store。
清单8. store的HTML定义
< div data-dojo-type="dojo.data.ItemFileReadStore" url="data.json"
data-dojo-id="store" urlPreventCache="true" clearOnClose="true">< /div>
清单8中的代码使用ItemFileReadStore来加载服务器端的data.json文件,并把结果与用作series的输入的store变量关联起来。数据存储类必须作为源文件require语句的一部分被请求加入应用中,如清单9所示。
清单9. 请求加入存储类
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojo/data/ItemFileReadStore",
"dojo/has!webKit?:dojox/mobile/compat",
"dojox/mobile", "dojox/mobile/parser",
"dojox/mobile/Button", "dojox/charting/widget/Chart",
"dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Grid"]);
现在你有了一个渲染来自服务器端的月度数据的移动图表应用了,但该例子仍然缺少应该显示目标月份而不是数据索引的x轴。清单10给出了轴的标签函数的引用。
清单10. 指定一个标签函数
< div class="axis" name="x"
fixUpper="minor" majorTickStep="1"
minorTicks="false" labelFunc="displayDate">< /div>
displayDate函数之后会在源文件中定义,如清单11所示。
清单11. 在JavaScript中实现标签函数
var displayDate;
require(["dojo/_base/kernel", "dojo/_base/sniff", "dojo/data/ItemFileReadStore",
"dojo/has!webKit?:dojox/mobile/compat",
"dojox/charting/action2d/TouchZoomAndPan",
"dojox/mobile", "dojox/mobile/parser",
"dojox/mobile/Button", "dojox/charting/widget/Chart",
"dojox/charting/axis2d/Default", "dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Grid"], function(dojo){
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"];
var years = ["08", "09", "10", "11"];
displayDate = function(idx){
if ((idx%2) == 0){
return " ";
}
var m = parseInt(idx-1);
if (m%12 == 0){
// Display the year only for january
return months[m%12] + " " + years[m/12];
}else{
return months[m%12];
}
}
});
清单11中的代码基本上是在把每项数据索引映射到一个串上。在这一例子中,因为有着超过三年的月度数据,所以使用指定索引的相应月份来形成串的内容。
你现在应该有能够得到如图2所示的结果。
图2. 定制轴标签
启用图表触摸交互
在创建了Dojo移动图表应用之后,你可能会想给它加上一些特有的移动功能,比如说能够使用触摸手势来与图表进行交互。这相对来说简单一些,与图表的其他功能相类似,你可以使用图表定义中的一行代码来加入触摸交互。例如,若要加入触摸缩放和平移功能的话,你只要把清单12中的内容加入到HTML标记中就可以了。
清单12. 加入对触摸缩放和平移的支持
< div class="action" type="dojox.charting.action2d.TouchZoomAndPan"
plot="plot" maxScale="7">< /div>
plot属性允许你把行为附加在图表的某个特定标定点上(在这一例子中是名为plot的标定点),你还可以使用其他各种选项,比如说是否允许缩放(enableZoom="false"),或是你想应用到图表上的最大缩放比例(maxScale="7")。
另一种很有用的触摸交互是在触摸图表时显示数据指示器,它甚至可以给出一个显示两个触摸点之间的趋势的双工数据指示器。
在单触摸图表时,使用清单13中的代码会产生图3中的结果。
清单13. 添加对触摸指示器的支持
< div class="action" type="dojox.charting.action2d.TouchIndicator" plot="plot"
series="data" dualIndicator="true">< /div>
图3. 交互式的简单的触摸指示器
你可使用双触摸手势来获得图4所示的结果。
图4. 交互式的双触摸指示器
关于触摸交互还有几个参数可用,比如说改变数据指示器的颜色和字体的能力。你甚至可以基于两个触点之间的趋势是正向的还是负向的来决定如何改变指示器的填充颜色。清单14给出的例子说明了如何在JavaScript中构建这样的一个指示器。
var indicatorFillFunc = function(v1, v2){
if(v2){
return v2.y>v1.y?"green":"red";
}else{
// single touch point
return "#ff9000";
}
};
var indicator = new TouchIndicator(chart, "plot", {
series: "series", dualIndicator: true,
font: "normal normal bold 12pt Helvetica",
fillFunc: indicatorFillFunc
});
某些移动设备,比如说Android 2.2和2.3,其并不支持浏览器中的多触摸事件,你可能会希望把某些依赖于双触摸的行为,比如说放大和缩小等,把这些行为映射到某些按钮和触摸交互上,以此来支持所有的设备。
就这种情况来说,自本文的第一个代码清单给出以来,用户界面上就已经存在了一些处于非活动状态的按钮,现在是时候添加一些代码来响应这些按钮的点击和触摸行为了。清单15说明了如何指定一个缩放函数。
清单15. 指定一个缩放函数
< button id="b1" data-dojo-type="dojox.mobile.Button"
onclick="zoomChart()"
class="mblBlueButton">Zoom< /button>
< button id="b2" data-dojo-type="dojox.mobile.Button"
onclick="zoomChart(true)"
class="mblBlueButton">Unzoom< /button>
清单15中的代码在zoom和unzoom按钮上都调用zoomChart函数,因为放大和缩小行为很类似,你只需使用一个带有参数的函数,并把缩小行为的参数值指定为true就可以了。
zoomChart函数在JavaScript源文件中做了定义,如清单16所示。其想法是获取当前的可视边界来计算出新的范围,然后把该范围传递给Dojo图表组件的zoomIn函数。
清单16. 在JavaScript中实现缩放函数
zoomChart = function(back){
var chart = dijit.byId("chart").chart;
var b = chart.getAxis("x").getScaler().bounds;
var r = 1.25;
if (back){
// Unzoom
chart.zoomIn("x", [b.from / r, b.to * r]);
}else{
// Zoom
chart.zoomIn("x", [b.from * r, b.to / r]);
}
};
优化应用
你现在有了一个完全能够运行的Dojo移动图表应用了,但它是没有完全优化过的。
你要进行的第一种优化是提高渲染时间,相比于桌面设备,移动设备通常会有着较慢的CPU和内存,因此渲染的过程也较慢。默认情况下,Dojo并不会缓存已经渲染过的图表像,在使用触摸交互来缩放和平移图表时,大量的已渲染项可能会被销毁并重建。在只有静态的图表时,不启用缓存是对的,因为这样会提供更快的初始渲染。然而在动态的使用情况下,最好是启用缓存,你可以使用几个图表元素的enableCache参数。
代码把图表元素上的enableCache设置成true,如清单17所示。
清单17. 优化渲染
< div data-dojo-type="dojox.charting.widget.Chart" id="chart"
style="width: 100%; height: 180px;">
< div class="plot" name="grid" type="Grid"
vMinorLines="true" enableCache="true">< /div>
< div class="axis" name="x" enableCache="true"
fixUpper="minor"
majorTickStep="1"
minorTicks="false"
labelFunc="displayDate">< /div>
< div class="axis" name="y" vertical="true" min="0">< /div>
< div class="plot" name="plot" type="Columns" enableCache="true">< /div>
< div class="series" name="data" store="store" plot="plot">< /div>
< div class="action" type="dojox.charting.action2d.TouchZoomAndPan"
plot="plot" maxScale="7">< /div>
< /div>
例子并未启用y轴上的缓存,在放大或是缩小时,图表沿着y轴方向并未重新渲染,因此不会从优化中受益。
另一种优化移动图表应用渲染的方法是阻止不必要的渲染,例如,柱图可能会有轮廓或是阴影,而这些并非是绝对必要的,但他们会消耗渲染时间,你可以考虑去掉它们。另一个例子是数据指示器,对于数据指示器来说,你可以通过把相应样式属性设置成null来取消轮廓线,如清单18所示。
清单18. 去掉不必要的渲染
< div class="action" type="dojox.charting.action2d.TouchIndicator" plot="plot"
series="data" dualIndicator="true" outline="null" lineOutline="null"
markerOutline="null">< /div>
应用加载时间的优化很重要,特别是移动设备的网络连接并不总是和桌面上的一样快。使用Dojo提供的新的AMD加载器,而不是同步加载各种所需的文件,你能够通过异步加载文件来提高整个的加载性能。在Dojo的初始配置中加入async参数,如清单19所示。
清单19. 启用异步的加载
< script type="text/javascript" src="../../../dojo_current/dojo/dojo.js" kesrc="../../../dojo_current/dojo/dojo.js"
data-dojo-config="parseOnLoad: true, async: true">< /script>
你可以通过除去任何不是应用绝对必需的实用工具来提高加载时间。例如,整个移动图表应用都是使用依赖于dojox.mobile解析器的标记来定义的,这一轻量级的解析器要比普通的Dojo解析器轻得多。如果真的想进一步降低应用的下载大小的话,你可以完全地去掉解析器,使用JavaScript来构建应用。
结论
在本文中,你了解了如何在移动web应用的内部使用Dojo图表包,它可以为依赖触摸交互事件而非依赖鼠标或按钮样式的移动设备提供量身定制的功能。本文还探讨了一些高级的可选功能项,你可以使用这些选项来改善加载和渲染时间。
如果你有兴趣进一步深入这一主题话,由于Dojo图表被设计成是可扩展的,因此你可以在其之上构建自己的功能。例如,如果你需要的一种触摸交互是框架没有提供的,那么你就可以扩展Dojo的图表行为包来创建自己的交互行为。
下载
描述 名称 大小 下载方法
源代码 source.zip 10KB HTTP
参考资料
学习资料
1. 阅读 Asynchronous Modules Come to Dojo 1.6,一篇关于AMD的博客文章。
2. 重温Dojo charting文档。
3. “Get started with Dojo Mobile 1.6”(developerWorks, June 2011)介绍如何在应用中包含和使用Dojo Mobile部件和组件,还可以了解如何使用PhoneGap来把web应用包装在本地化应用中。
4. 看一看IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile Showcase中的移动图表例子。
5. 了解WebSphere Application Server Feature Pack for Web 2.0 and Mobile。
获得产品和技术
1. 获取Dojo Toolkit。
2. 下载IBM产品的评估版本,动手使用来自DB2、Lotus、Rational、Tivoli和WebSphere的应用开发工具和中间件产品。
讨论
1. 现在就创建你的developerWorks个人资料,并设置一个关于Dojo的观看列表。与developerWorks社区建立联系并保持联系。
2. 找到其他在web开发方面感兴趣的developerWorks成员。
3. 分享你的知识:加入一个关注web专题的developerWorks组。
4. Roland Barcia在他的博客中谈论Web 2.0和中间件。
5. 关注developerWork成员的shared bookmarks on web topics。
6. 快速获得答案:访问Web 2.0 Apps论坛。
7. 快速获得答案:访问Ajax论坛。关于作者
Christophe Jolif是IBM France的一位顾问软件工程师,他领导IBM ILOG Elixir开发团队,并且是Dojo Toolkit开源项目的捐献者。他在团队博客和一些技术文章中撰写 ILOG Elixir方面的内容,并还为产品的技术文档贡献了自己的一部分力量。在加入IBM之前,Christophe为ILOG工作超过十年,开发出了用在Java™、Ajax、Adobe® Flex中的先进的可视化组件。
Damien Mandrioli是IBM的一位软件工程师,他的专业兴趣包括了可视化组件、web应用开发和用户界面的可用性。在加入Dojo Toolkit开发团队之前,Damien花费了五年的时间来开发IBM ILOG Elixir可视化产品的组件和演示应用。
相关文章: