日期:2014-05-16  浏览次数:20458 次

Extjs YUI Charts 实现原理分析
首先说一下 YUI Extjs Astra三者的Charts的关系:
Extjs原名YUI-Extjs,最初Extjs是对YUI的封装
Extjs 3.0新增的Charts功能实际上是对YUI Charts的封装
YUI Charts是对Astra Charts的封装
Astra Charts是Astra Flash Components的组件之一
Astra Flash Components是YAHOO提供的flash/flex组件库
Extjs和YUI两者实现CHARTS的示例代码:
//yui LineChart 核心代码
var mychart = new YAHOO.widget.LineChart( "chart", myDataSource,
{
series: seriesDef,
xField: "month",
yAxis: currencyAxis,
dataTipFunction: YAHOO.example.getDataTipText,
//only needed for flash player express install
expressInstall: "assets/expressinstall.swf"
});

//extjs LineChart 核心代码
new Ext.Panel({
        title: 'ExtJS.com Visits Trend',
        renderTo: 'container',
        width:500,
        height:300,
        layout:'fit',
        items: {
            xtype: 'linechart',
            store: store,
            xField: 'name',
            yField: 'visits',
listeners: {
itemclick: function(o){
var rec = store.getAt(o.index);
Ext.example.msg('Item Selected', 'You chose {0}.', rec.get('name'));
}
}
        }
    });

具体实现代码大家请参考官方网站:
http://extjs.com/deploy/dev/examples/chart/charts.html
http://developer.yahoo.com/yui/charts/
由于Extjs的charts功能只是对YUI charts的封装所以我这里只是介绍一下YUI Charts的实现原理。
首先看一下YUI Charts主要类结构

YAHOO.widget.Chart是所有Chart的基类,其中饼图YAHOO.widget.PieChart是直接继承YAHOO.widget.Chart;而其他柱状图、连线图等其他图形是继承 YAHOO.widget.CartesianChart。而YAHOO.widget.Chart的父类YAHOO.widget.FlashAdapter是实现Chart功能最重要的类,就像它的名字显示的含义一样这个类是js和flash交互的适配器。
下面再看一下为了支持YUI实现Charts功能YUI在Astra Charts上进行的封装

右边2个类是Astra Charts原有的类
YUIAdapter和Charts是为了YUI实现Chart相关功能对Astra Charts进行的封装
Sprite 是不需要时间轴的对象的相应基类。
下面看一下YAHOO.widget.LineChart的初始化过程,也就是执行上面第一段代码时的时序图
上图中的XXXChart代表YAHOO.widget.LineChart的一些父类,这里为了画图时简单一点。
new YAHOO.widget.LineChart( …)构造Chart对象,实质上是调用父类的构造函数,最终调用FlashAdapter的构造函数。FlashAdapter的私有方法_embedSWF中创建了一个SWFObject对象
	/**
	 * Embeds the SWF in the page and associates it with this instance.
	 *
	 * @method _embedSWF
	 * @private
	 */
	_embedSWF: function(swfURL, containerID, swfID, version, backgroundColor, expressInstall, wmode)
	{
		//standard SWFObject embed
		var swfObj = new YAHOO.deconcept.SWFObject(swfURL, swfID, "100%", "100%", version, backgroundColor);

		if(expressInstall)
		{
			swfObj.useExpressInstall(expressInstall);
		}

		//make sure we can communicate with ExternalInterface
		swfObj.addParam("allowScriptAccess", "always");
		
		if(wmode)
		{
			swfObj.addParam("wmode", wmode);
		}
		
		//again, a useful ExternalInterface trick
		swfObj.addVariable("allowedDomain", document.location.hostname);

		//tell the SWF which HTML element it is in
		swfObj.addVariable("elementID", swfID);

		// set the name of the function to call when the swf has an event
		swfObj.addVariable("eventHandler", "YAHOO.widget.FlashAdapter.eventHandler");

		var container = YAHOO.util.Dom.get(containerID);
		var result = swfObj.write(container);
		if(result)
		{
			this._swf = YAHOO.util.Dom.get(swfID);
			//if successful, let's add an owner property to the SWF reference
			//this will allow the event handler to communicate with a YAHOO.widget.FlashAdapter
			this._swf.owner = this;
		}
		else
		{
			YAHOO.log("Unable to load SWF " + swfURL);
		}
	},

上面的代码注释大家应该基本可以看明白是怎么回事,我再稍微做一下解释。
SWFObject是一种易用的、符合标准的在网页中嵌入flash对象的方法 ,能够自动检测PC、Mac机器上各种主流浏览器对Flash插件的支持情况。
SWFObject属于另一个开源项目:http://code.google.com/p/swfobject/
swfObj.addParam(“allowScriptAccess”, “always”);//allowscriptaccess=always 允许随时执行脚本操作  使 Flash 应用程序可与其所在的 HTML 页通信
swfObj.addVariable(“allowedDomain”, document.location.hostname);//actionscript与JS的交