PREFUSE-FLARE学习报告

前端之家收集整理的这篇文章主要介绍了PREFUSE-FLARE学习报告前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

[@H_301_9@简介]@H_301_9@@H_301_9@

flare@H_301_9@加利福尼亚大学伯克利分校(University of California@H_301_9@,Berkeley@H_301_9@)可视化研究实验室所开发的一面向WEB@H_301_9@数据可视化应用的、开源的项目,它的前身是有名的prefuse@H_301_9@,一个用于交互式数据可视化的JAVA@H_301_9@类库。此项目旨在使交互式数据可视化工作变得容易。与它的前身prefuse@H_301_9@不同,flare@H_301_9@是一个ActionScript@H_301_9@库,运行于Adobe Flash Player@H_301_9@之上,可以与当下十分流行的FLEX@H_301_9@开发工具结合进行十分炫丽的数据可视化工作。从基本的图表到复杂的交互式图形,这个工具包提供包括数据管理、可视化编码、动画和交互技术等一系列支持。更重要的是,flare@H_301_9@提供的模式化的设计可以让开发者免去很多不必要的重复性工作而建立一些定制好了的可视化技术。Flare@H_301_9@是一个遵从BSD license@H_301_9@的开源软件。你可以从它的官方网站@H_301_9@@H_301_9@http://flare.prefuse.org@H_301_9@上获得更多的信息。下面是一个flare@H_301_9@的应用。@H_301_9@@H_301_9@

@H_301_9@@H_301_9@

[@H_301_9@关键字]@H_301_9@@H_301_9@

Flare@H_301_9@;数据可视化;WEB@H_301_9@;开源@H_301_9@@H_301_9@

 @H_301_9@

[@H_301_9@需求分析]@H_301_9@@H_301_9@

数据可视化技术使得人们不再局限于通过文本或关系数据表来观察和分析数据信息,转而以更直观的方式研究数据并发现其中隐藏的关系,将单调乏味的数据及其内涵关系美观形象地展现在人们面前。根据实现原理的不同,数据可视化方法可以划分为基于几何的技术、面向像素的技术、基于图表的技术、基于层次的技术、基于图像的技术和分布式技术等。在很多领域中,数据可视化都在数据分析与数据挖掘中发挥了重要的作用,但是这些可视化往往做得比较简单,如果要做出效果炫丽的可视化图表,往往要花费很大的投入。为了满足目前越来越多的对大量数据进行可视化研究的需求,尤其是网站中海量数据的可视化需求,人们急切地需要一个专门用于数据可视化的工具,来帮助人们简单快捷地搭建基于自己数据的可视化效果@H_301_9@@H_301_9@

 @H_301_9@

软件组成及使用方法@H_301_9@@H_301_9@

下面来简单介绍一下软件的组成以及如何用flare@H_301_9@快速地搭建自己的数据可视化效果@H_301_9@@H_301_9@

首先要获得flare@H_301_9@开发工具集。@H_301_9@@H_301_9@

1、 @H_301_9@@H_301_9@@H_301_9@建立一个flash@H_301_9@开发环境。@H_301_9@@H_301_9@

这可以通过两种方式来实现,一种是使用Adobe@H_301_9@公司的Flex Builder@H_301_9@。这是一个完整的AS/FLEX@H_301_9@开发环境,但是要注意,FLEX BUILDER@H_301_9@是一个商业软件,但是ADOBE@H_301_9@为在校大学生,和大学教职工提供此软件的免费授权,所以对我们而言,这是一种最方便的建立FLASH@H_301_9@开发环境的方式。当然,如果你不想这样,你也可以安装一个免费的FLEX SDK@H_301_9@,大多数进阶的用户都更喜欢使用这种方式。这种方式将只安装基本的AS/FLEX@H_301_9@编译器:mxmlc@H_301_9@和compc@H_301_9@。然后你就可以创建自己的开发环境了。更多细节请到flare@H_301_9@官方网站上查询@H_301_9@@H_301_9@

2、 @H_301_9@@H_301_9@@H_301_9@下载prefuse-flare@H_301_9@库。@H_301_9@@H_301_9@

下载的工具包包括一组AS@H_301_9@库工程,然后把它们解压到你的工作目录之下就可以了,如果你用的是FB@H_301_9@。在随后的内容中,我会介绍如何导入这些文件来建立一个可视化工程。@H_301_9@@H_301_9@

 @H_301_9@

第一部分:显示对象@H_301_9@@H_301_9@

 @H_301_9@

简介:@H_301_9@@H_301_9@

FLASH@H_301_9@使用“场景图”@H_301_9@[1]@H_301_9@scenegraph@H_301_9@)来构建一个二维的可视化场景,可视化对象以一种层次结构组织,子对象嵌入在父对象的坐标空间中。在ADOBE@H_301_9@的文档和FLASH@H_301_9@编程的书中,你会经常看到场景图被称作“显示表”(display list@H_301_9@)。在这个显示表的最高层次的结点总是舞台对象,而且它有且仅有一个孩子结点,这就是所谓的“根结点”。所有能够加在这个显示列表里的可视元件都是DisplayObject@H_301_9@这个类的实例,DisplayObject@H_301_9@包括Bitmap,TextField@H_301_9@和Video@H_301_9@。最常见的就是Sprite@H_301_9@和Shape@H_301_9@类了,它们可以在flash.display@H_301_9@这个包里找到。@H_301_9@@H_301_9@

建立一个新的应用:@H_301_9@@H_301_9@

首先让我们来建立一个新的FLASH@H_301_9@应用。打开FLEX BUILDER@H_301_9@并确认你是在Flex@H_301_9@开发视图之下,在左边的“Navigator”@H_301_9@面板里,右键点击“display”@H_301_9@并且选择“New->ActionScript Project”@H_301_9@。在接下来的对话框里,以“Tutorial”@H_301_9@为名建立一个工程。@H_301_9@@H_301_9@

然后你就会在“Navigator”@H_301_9@面板中看到这个文件夹,你会在其中看到一个名字“Tutorial.as”@H_301_9@的文件,这就是你的应用程序文件。打开这个文件@H_301_9@@H_301_9@

@H_301_9@

在这个文件里,你会看到这个类的基本框架:@H_301_9@@H_301_9@

package {@H_301_9@

    @H_301_9@import flash.display.Sprite;@H_301_9@

 @H_301_9@

    @H_301_9@public class Tutorial extends Sprite@H_301_9@

    @H_301_9@{@H_301_9@

        @H_301_9@public function Tutorial()@H_301_9@

        @H_301_9@{@H_301_9@

        @H_301_9@}@H_301_9@

    @H_301_9@}@H_301_9@

}@H_301_9@

注意这个类继承了Sprite@H_301_9@类,因为这是我们的主类,当我们运行Tutorial@H_301_9@类中的一个应用实例时,它会自动地将显示列表添加为根结点。@H_301_9@@H_301_9@

同时也要注意到,一个结构体同时也被建立起来了。这个结构体会在应用被执行时被调用,这点跟大家所熟悉的JAVA,C++@H_301_9@里的main()@H_301_9@函数分类似。@H_301_9@@H_301_9@

有了这个应用程序框架,我们就可以用可视化对象进行演示了。但是在这之前,我们还有另一件事要做。在“public class Tutorial”@H_301_9@一行下,添加如下代码@H_301_9@@H_301_9@

[SWF(width="800",height="600",backgroundColor="#ffffff",frameRate="30")]@H_301_9@

这一行代码定义了你的应用的默认设置,它将会被编译并且以“a.swf”@H_301_9@为文件名在你的工程目录下的“bin@H_301_9@”文件夹中。上面这一步,我们为这个应用设置了窗体的大小,背景颜色和目标的帧频。@H_301_9@@H_301_9@

Sprites@H_301_9@

跟所有的DisplayObjects@H_301_9@一样,Sprite@H_301_9@支持一系列的可视化属性包括x,y@H_301_9@坐标,以及在这些方向的缩放等,这些都是根结点的孩子结点,因为正如前面所说,我们使用的是“场景图”。@H_301_9@@H_301_9@

然而,这些值尚没有什么意义,因为sprites@H_301_9@默认不包含任何数据。下面我们就将来在其中添入我们自己的内容@H_301_9@@H_301_9@

每一个sprite@H_301_9@都具有图形性质,我们可以利用这一点来为它绘制图形。这些图形属性flash.display.Graphics@H_301_9@类的一个实体,包括了一系列的矢量绘图命令。@H_301_9@@H_301_9@

接下来,我们还要做很多事。@H_301_9@@H_301_9@

首先,建立一个新的Sprite@H_301_9@。@H_301_9@@H_301_9@

然后,我们利用它的图形性质画一个填充为灰色,线条为黑色的圆。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@beginFill@H_301_9@设定当前的填充和外观,第一个参数是颜色,第二个是透明度。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@lineStyle@H_301_9@设定当前线条的颜色和外观,第一个参数指定线宽,第二个指定颜色。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@drawCircle@H_301_9@用来在sprite@H_301_9@的坐标空间描绘一个半径为10@H_301_9@的圆。@H_301_9@@H_301_9@

第三,我们把sprite@H_301_9@添加为我们主应用程序的子类。@H_301_9@@H_301_9@

第四,为我们的sprite@H_301_9@设定x,y@H_301_9@坐标;@H_301_9@@H_301_9@

第五,我们添加一些debug@H_301_9@输出Trace@H_301_9@用来在会话窗口中显示一串字符,这串字符只有当我们在“debug”@H_301_9@模式下运行应用程序时才会显示@H_301_9@@H_301_9@

下面是代码@H_301_9@@H_301_9@

package {@H_301_9@

    @H_301_9@import flash.display.Sprite;@H_301_9@

 @H_301_9@

    @H_301_9@[SWF(width="800",frameRate="30")]@H_301_9@

    @H_301_9@public class Tutorial extends Sprite@H_301_9@

    @H_301_9@{@H_301_9@

        @H_301_9@public function Tutorial()@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@var sprite:Sprite = new Sprite();@H_301_9@

 @H_301_9@

            @H_301_9@sprite.graphics.beginFill(0xcccccc,0.5);@H_301_9@

            @H_301_9@sprite.graphics.lineStyle(1,0x000000);@H_301_9@

            @H_301_9@sprite.graphics.drawCircle(0,10);@H_301_9@

 @H_301_9@

            @H_301_9@this.addChild(sprite);@H_301_9@

 @H_301_9@

            @H_301_9@sprite.x = 50;@H_301_9@

            @H_301_9@sprite.y = 50;@H_301_9@

            @H_301_9@trace("our sprite is at: "+sprite.x+","+sprite.y);@H_301_9@

        @H_301_9@}@H_301_9@

    @H_301_9@}@H_301_9@

}@H_301_9@

右键点击“Tutorial.as”@H_301_9@,选择“Run as->Flex Application”@H_301_9@来运行这个程序。你就会看到下面显示结果了。如果是在Debug@H_301_9@模式下,你还会在会话窗口看到“our sprite is at: 50,50”@H_301_9@这样一串字符。@H_301_9@@H_301_9@

@H_301_9@

嵌套Sprites@H_301_9@@H_301_9@

现在让我们来做一点有趣的事情。把下面的方法添加到我们的类中:@H_301_9@@H_301_9@

private function createCircle(x:Number,y:Number):Sprite@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@var sprite:Sprite = new Sprite();@H_301_9@

 @H_301_9@

            @H_301_9@sprite.graphics.beginFill(0xcccccc,10);@H_301_9@

            @H_301_9@sprite.x = x;@H_301_9@

            @H_301_9@sprite.y = y;@H_301_9@

            @H_301_9@return sprite;@H_301_9@

        @H_301_9@}@H_301_9@

然后,把我们原来结构体中的代码用如下的代码替换。先要建立一个名为container[2]@H_301_9@的新sprite@H_301_9@,我们将用它来存放一个圆集。我们把它放在我们的舞台中央。接下来我们使用一个循环来建立一串圆,把这些圆以原点为中间对称地排列起来。代码如下:@H_301_9@@H_301_9@

public function Tutorial()@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@var container:Sprite = new Sprite();@H_301_9@

            @H_301_9@container.x = 400;@H_301_9@

            @H_301_9@container.y = 300;@H_301_9@

            @H_301_9@this.addChild(container);@H_301_9@

 @H_301_9@

            @H_301_9@for (var i:int=0; i<10; ++i) {@H_301_9@

                @H_301_9@var x:Number = (i/5<1 ? 1 : -1) * (13 + 26 * (i%5));@H_301_9@

                @H_301_9@container.addChild(createCircle(x,0));@H_301_9@

            @H_301_9@}@H_301_9@

        @H_301_9@}@H_301_9@

运行一下这个新的程序,你会看到一排十个圆显示在你的程序舞台中央。@H_301_9@@H_301_9@

@H_301_9@

运用我们刚才介绍的参数,你可以随意地做出各种不同的有趣的可视效果。试试看!@H_301_9@@H_301_9@

关于Flash@H_301_9@的其它主题@H_301_9@@H_301_9@

使用FLASH@H_301_9@提供的基本的选项,你还可以做很多事情。不幸的是,我们没有足够的时间来说这些。你可以自行了解一些关于图片过滤(在flash.filters@H_301_9@包中)和图形绘制的更多信息。@H_301_9@@H_301_9@

 @H_301_9@

第二部分:动画@H_301_9@@H_301_9@

 @H_301_9@

现在我们已经可以建立一些简单的可视对象了,是时候加一点更加生动的东西了。Flare@H_301_9@在flare.animate@H_301_9@包中包含了一些可以帮助我们轻松实现动画的东西。首先,我们要把flare@H_301_9@类库引入到Flex Builder@H_301_9@之中。@H_301_9@@H_301_9@

导入库文件@H_301_9@@H_301_9@

开始之前,一定要确认你的flare@H_301_9@类库以工程的方式加载在你的flexbuilder@H_301_9@之中。你应该已经把你的下载的flare@H_301_9@文件解压到了你的flexbuilder@H_301_9@工作空间目录中,这里我们把这些文件放在一个名为“flare-alpha”@H_301_9@文件夹下。下一步就是把它导入到你的flexbuilder@H_301_9@环境之中。@H_301_9@@H_301_9@

1、  @H_301_9@@H_301_9@@H_301_9@确认你是在“flex development”@H_301_9@界面中。@H_301_9@@H_301_9@

2、  @H_301_9@@H_301_9@@H_301_9@在导航栏里右键单击(注意一定要单击空白区域),@H_301_9@@H_301_9@

3、  @H_301_9@@H_301_9@@H_301_9@菜单中选择“import”@H_301_9@。@H_301_9@@H_301_9@

4、  @H_301_9@@H_301_9@@H_301_9@在对话框中,选择“general->Existing Projects into Workspace@H_301_9@”,然后点击“Next”@H_301_9@按钮。@H_301_9@@H_301_9@

5、  @H_301_9@@H_301_9@@H_301_9@使用“Select root directory”@H_301_9@小工具来导航到Flex Builder@H_301_9@工作空间目录下的“flare-alpha”@H_301_9@文件夹。@H_301_9@@H_301_9@

6、  @H_301_9@@H_301_9@@H_301_9@你现在应该就可以在“Projects”@H_301_9@面板中看到flare@H_301_9@工程了。@H_301_9@@H_301_9@

7、  @H_301_9@@H_301_9@@H_301_9@选择“flare@H_301_9@”中的“flare.demos”@H_301_9@工程,然后点击“Finish”@H_301_9@按钮。@H_301_9@@H_301_9@

现在你就可以在导航栏里看flare@H_301_9@工程文件了,也就是,除了刚才的Tutorial@H_301_9@,还增加了一个flare@H_301_9@和一个flare.demo@H_301_9@文件夹,在这两个文件夹里,你就可以分别查看到flare@H_301_9@库和演示的源代码了。@H_301_9@@H_301_9@

Flare@H_301_9@文件概览@H_301_9@@H_301_9@

我们来大致看一下flare@H_301_9@工具包。首先来看“src/flare”@H_301_9@这个文件夹,你会看到提供不同特性的一系列packages:@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@analytics@H_301_9@:提供统计运算与数据分析操作工具@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@animate@H_301_9@:建立动画的工具@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@data@H_301_9@:读/@H_301_9@写数据的方法@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@display@H_301_9@:一些从flash.display@H_301_9@中拓展而来的DisplayObject@H_301_9@类型@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@flex@H_301_9@:将flare@H_301_9@可视化组件植入flex@H_301_9@的封装@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@physics@H_301_9@:一个用于物理效果和应力布局物理引擎@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@query@H_301_9@:为ActionScript@H_301_9@对象而设计的查询进程。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@scale@H_301_9@:一些进行数据缩放的类,如线性缩放,对数缩放,时域缩放等。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@util@H_301_9@:一组可提供常用功能的通用类@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@vis@H_301_9@Flare@H_301_9@可视化的组件和算子@H_301_9@@H_301_9@

把一个类库导入到其它的项目中@H_301_9@@H_301_9@

为了能够在你自己的项目中使用flare@H_301_9@,你需要更新你的项目预设。下面来介绍一下如何更新:@H_301_9@@H_301_9@

1、  @H_301_9@@H_301_9@@H_301_9@在导航面板中,右击“Tutorial”@H_301_9@项目的最顶层文件夹;@H_301_9@@H_301_9@

2、  @H_301_9@@H_301_9@@H_301_9@在出现的菜单中单击“Properties@H_301_9@”;@H_301_9@@H_301_9@

3、  @H_301_9@@H_301_9@@H_301_9@在接下来的对话框中,单击左侧面板中的“ActionScript Build Path@H_301_9@”;@H_301_9@@H_301_9@

4、  @H_301_9@@H_301_9@@H_301_9@在右侧面板中单击“Library path”@H_301_9@;@H_301_9@@H_301_9@

5、  @H_301_9@@H_301_9@@H_301_9@单击“Add Project”@H_301_9@按钮;@H_301_9@@H_301_9@

6、  @H_301_9@@H_301_9@@H_301_9@你现在应该可以看到一个项目列表,包括flare@H_301_9@;@H_301_9@@H_301_9@

7、  @H_301_9@@H_301_9@@H_301_9@选择“flare@H_301_9@”并单击“OK@H_301_9@”。@H_301_9@@H_301_9@

现在你就把flare@H_301_9@类加入到你的工程中,并可以使用所有它所提供的类了。@H_301_9@@H_301_9@

有一件需要注意的事是关于Flex@H_301_9@编译器的。默认情况下,它只包含那些你真正使用在你的应用程序中的类。所以即使你导入了一个非常大的库,你的最终文件,一个.swf@H_301_9@文件仍然会很小。但是,要知道,如果你在你的应用中使用映射进行动态的类加载,这将会导致某些问题。这个问题我们将不在这个tutorial@H_301_9@示例中涵盖。@H_301_9@@H_301_9@

基本动画:补间,序列和平行@H_301_9@@H_301_9@

好了,让我们来进行动画的设计吧!flare.animate.Transition@H_301_9@类是一个所有动画的基础类。Transition@H_301_9@(滤镜)重要的子类包括补间,序列和平行滤镜。补间用来对单个对象创建动画,序列用来按一定顺序组织运行一系列的动画,平行滤镜可以用来同时执行一组滤镜。我们从Tween@H_301_9@开始吧。@H_301_9@@H_301_9@

Tween@H_301_9@类很简单,我们拿来一个对象,然后给它安排一组随时间变化的属性值,并确定这些变化的时间间隔。继续使用第一部分我们所建立的应用,在Tutorial@H_301_9@结构体的后面加入下面的几行:@H_301_9@@H_301_9@

var tween:Tween = new Tween(container,3,{rotation:360});@H_301_9@

tween.play();@H_301_9@

并且,确认你在顶部有一个导入声明,以便让编译器知道你使用了它。下面是需要加入的一行代码@H_301_9@@H_301_9@

@H_305_1404@import flare.animate.Tween;@H_301_9@

@H_305_1404@现在来运行你的程序,你会看到那些点以在3@H_301_9@秒钟的时间内进行旋转。@H_301_9@@H_301_9@

你或许已经发现这个旋转运动是加速进行的,这是因为在tween@H_301_9@实例的默认设置里使用了“slow-in slow-out@H_301_9@”动画。你可以使用Easing@H_301_9@函数来来控制这些行为。这些函数把当前进行中的运动作为一个介于0@H_301_9@和1@H_301_9@之间的分数作为参数,然后返回一个处理过的分数来改变运动的节奏,通常是以一种非线性的方式。@H_301_9@@H_301_9@

要想移除easing@H_301_9@,你可以写:@H_301_9@@H_301_9@

tween.easing=Easing.none@H_301_9@@H_301_9@

但是你需要确认你在文件的顶层导入了flare.animate.Easing@H_301_9@类。@H_301_9@@H_301_9@

实际上你可以自由地在easing@H_301_9@函数上做一些其它的试验,我这里就不作过多描述了。@H_301_9@感兴趣的话,你还可以尝试改变一下容器的其它属性,如位置,缩放,透明度等,留给读者自行研究,这里不再讨论。@H_301_9@@H_301_9@

复合动画@H_301_9@@H_301_9@

Sequence@H_301_9@parallel@H_301_9@类使得我们可把很多动画组织在一起。Sequence@H_301_9@用来使一组动画一个接一个地运行,例如,试试下面的代码@H_301_9@@H_301_9@

var t1:Tween = new Tween(container,1,{y:100});@H_301_9@

var t2:Tween = new Tween(container,{scaleX:2});@H_301_9@

var t3:Tween = new Tween(container,{y:300});@H_301_9@

var t4:Tween = new Tween(container,{scaleX:1});@H_301_9@

var seq:Sequence = new Sequence(@H_301_9@

    @H_301_9@new Parallel(t1,t2),@H_301_9@

    @H_301_9@new Parallel(t3,t4)@H_301_9@

);@H_301_9@

seq.play();@H_301_9@

同样,你也需要在你文件的顶部加上一些导入声明:@H_301_9@@H_301_9@

import flare.animate.Parallel;@H_301_9@

import flare.animate.Sequence;@H_301_9@

这样我们建立了四个tween@H_301_9@:t1,t2,t3@H_301_9@和t4@H_301_9@。它建立了两个平行滤镜:一个把t1@H_301_9@和t2@H_301_9@运行在一起,一个把t3@H_301_9@和t4@H_301_9@运行在一起。然后平行滤镜就会让他们按照先后顺序执行。同样,可以很容易地创建一些更加复杂的动画。@H_301_9@@H_301_9@

想要对进阶的复合动画了解更多,可以看一下Flarelogo@H_301_9@和在flare.demos@H_301_9@工程中的flare.demos.Animation@H_301_9@类。@H_301_9@@H_301_9@

带滤镜的批量动画@H_301_9@@H_301_9@

使用tween,parallel@H_301_9@和sequence@H_301_9@类,你可以创建包含任意数量动画的动画滤镜。但是,当处理一大堆对象的时候,手动地管理同样一大堆tweens@H_301_9@是很痛苦的一件事情。而且,基于那些像轮廓、颜色、大小和形状这些可视属性而运行分立的功能要简单一些,因为我们不需要为控制动画而担心。你可能是想要把变化以动画的形式表现出来,也可能是,你只需要一个静态的更新。但是不管如何,你最好能够做到对已分配的值进行重复利用。@H_301_9@@H_301_9@

出于对这些的考虑,flare@H_301_9@提供了一个Transitioner@H_301_9@类。Transitioners@H_301_9@简化了为大量对象建立动画的过程,你只需要选择一个对象,然后对这个对象的属性一一设置好就可以了。在舞台后面,transitioner@H_301_9@会自动生成并重复利用必要tweens@H_301_9@来开成整个的动画。而且,如果一个动画不是急需的,这个transitioner@H_301_9@可以被指定转而设置一些即时的属性值。简单地说,transitioner@H_301_9@为对象属性值的更新提供了一个间接的层,使得这些更新可以收集起来并运用到动画中去,或者被直接运行。@H_301_9@@H_301_9@

这里有一个使用transitioner@H_301_9@的例子,仍然需要用到我们的tutorial@H_301_9@程序。@H_301_9@@H_301_9@

var t:Transitioner = new Transitioner(2);@H_301_9@

for (var j:int=0; j<container.numChildren; ++j) {@H_301_9@

     @H_301_9@var s:Sprite = container.getChildAt(j) as Sprite;@H_301_9@

     @H_301_9@t.$(s).y = 200 * (Math.random() - 0.5);@H_301_9@

     @H_301_9@t.$(s).scaleY = 1 + 2*Math.random();@H_301_9@

}@H_301_9@

t.play();@H_301_9@

这个示例赋予了容器中所有的sprite@H_301_9@一个新的、随机y@H_301_9@坐标和一个随机的垂直绽放因子,我们首先建立了一个可以创建一个2@H_301_9@秒动画的动画,然后我们循环遍历每一个子结点上的sprite@H_301_9@并且使用transitioner@H_301_9@来为tween@H_301_9@设定属性值。@H_301_9@@H_301_9@

Transitioner@H_301_9@flare.vis@H_301_9@包里有有着大量的应用,它使得可视化设计人员可以掌控哪些更新是被动态化的以及如何动态化的。@H_301_9@@H_301_9@

第三部分:visualizations@H_301_9@@H_301_9@

加载数据@H_301_9@@H_301_9@

Flare@H_301_9@中基本的数据表示方法只是简单地使用了flash@H_301_9@中内置的数据类型:对象与数组。例如,一个数据表就可以表示一组对象,这些对象又包含了每一个数域的名称和数值。然而更有效的表示方法也是可能的,这种方法提供了一种灵活性,同时还使得flash@H_301_9@现有的一些开发惯例获益。@H_301_9@@H_301_9@

要把数据加载到flash player@H_301_9@有很多种方法。一个简单的做法是把你的数据嵌入到你的应用程序之中。这样的话,数据的下载是跟随应用程序的编译与运行是同时进行的,这对静态数据而言没什么不便。例如,你可以使用ActionScript@H_301_9@的对定义方式来直接把一个数据定义为变量:@H_301_9@@H_301_9@

var data:Array = [@H_301_9@

    @H_301_9@{id:"Q1",sales:10000,profit:2400},@H_301_9@

    @H_301_9@{id:"Q2",sales:12000,profit:2900},@H_301_9@

    @H_301_9@{id:"Q3",sales:15000,profit:3800},@H_301_9@

    @H_301_9@{id:"Q4",sales:15500,profit:3900}@H_301_9@

];@H_301_9@

然而,更多的时候我们需要动态地加载我们的数据。这也有很多途径可供选择,例如,ActionScript@H_301_9@提供附加的数据类型和语法来同XML@H_301_9@数据工作在一起。@H_301_9@@H_301_9@

Flare@H_301_9@也提供一些加载外部数据的常用函数。它可以从任何服务器加载数据,然后转化成ActionScript@H_301_9@的内部对象。对于远程数据,flare@H_301_9@则使用flare.data.DataSource@H_301_9@类来进行加载。这里是一个用它来加载一个名为“test.tab.txt@H_301_9@”文件里的数据的例子:@H_301_9@@H_301_9@

var ds:DataSource = new DataSource(@H_301_9@

    @H_301_9@"http://flare.prefuse.org/data/test.tab.txt","tab"@H_301_9@

);@H_301_9@

var loader:URLLoader =  @H_301_9@ds.load();@H_301_9@

loader.addEventListener(Event.COMPLETE,function(evt:Event):void {@H_301_9@

    @H_301_9@// function to handle data once loading is complete@H_301_9@

    @H_301_9@var ds:DataSet = loader.data as DataSet;@H_301_9@

    @H_301_9@// now do something with the data...@H_301_9@

});@H_301_9@

对于那些图式可能不干净的数据集,有一个第三方的、可选的DataSchema@H_301_9@型的结构可用。你可以从flare.data.DataSchema@H_301_9@和flare.data.DataField@H_301_9@类中来了解更多关于它的知识。@H_301_9@@H_301_9@

如果想要真正意义上地加载数据,可调用DataSource@H_301_9@加载方法并返回一个flash.net.URLLoader@H_301_9@实例。这个加载器可以用来追踪下载活动并且会在下载完成时发出一个通知。在上面的例子中,我们通过加入一个事件侦听器来通知用户何时加载完成。DataSource@H_301_9@会自动转换输入的数据并将其映射为ActionScript@H_301_9@对象,然后保存在flare.data.DataSet@H_301_9@对象中。这些保存的数据既可以用表,也可以用图来呈现。想获得更多细节,可以查看API@H_301_9@参考手册。@H_301_9@@H_301_9@

建立和管理可视对象@H_301_9@@H_301_9@

现在我们应该可以可视化地呈现一组数据了。要做到这个,我们把不可见的数据映射为可见的元件。Flare@H_301_9@提供一组可视对象来呈现数据。下面是一个对flare@H_301_9@在flare.vis.data@H_301_9@包中提供的基本的类的一个概览。@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@DataSprite:sprite@H_301_9@中可视化地显示数据的一个基本类;@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@NodeSprite:@H_301_9@用来将DataSprite@H_301_9@实例呈现为一个结点,这是用来可视化数据的类型;@H_301_9@@H_301_9@

Ø  @H_301_9@@H_301_9@@H_301_9@EdgeSprite:@H_301_9@用来将DataSprite@H_301_9@实例呈现为一个边,一个EdgeSprite@H_301_9@用来连接两个NodeSprite.@H_301_9@@H_301_9@

准确地说,NodeSprite@H_301_9@和EdgeSprite@H_301_9@被建立并保存为flare.vis.data.Data@H_301_9@类,这个类用来为一个单独的可视化项目管理可视组件用。这个类为数据元组提供建立可视对象和以图形的方式呈现它们的方法@H_301_9@@H_301_9@

这个Data@H_301_9@类也提供一些用来转化和更新所包含的数据元件的方法。这些结点和边属性在返回一个包含在数据中的结点和边的列表。每一个列表包含一个允许你通过某个函数来到达每个边和结点的访问方法。并且,setProterty@H_301_9@和setProperties@H_301_9@方法允许你立即为所有的结点和属性设定属性值。这些方法可以选用一个Transitioner@H_301_9@作为参数,从而使你可以这些属性的更新动画化。@H_301_9@@H_301_9@

例如,下面这段代码实现了一个在1@H_301_9@秒钟之内将所有结点的边变成蓝色的动画。@H_301_9@@H_301_9@

data.nodes.setProperty("lineColor",0xff0000bb,new Transitioner(1)).play();@H_301_9@

结点和边列表也支持通过使用setDefault,setDefaults,removeDefault@H_301_9@和clearDefaults@H_301_9@方法来默认的属性值。一个使用addNode@H_301_9@或addEdgeFor@H_301_9@方法新建立的新结点或边会被赋予默认值。@H_301_9@@H_301_9@

树类是Data@H_301_9@类的一个子类,专门用来表现一棵树。Data@H_301_9@类支持通过计算一个一般表的生成树来建立一个树实例。如深度优先、广度优先、最小生成树等很多生成树算法都可以作为一个参数传递给它。这些计算是通过使用flare.analytics.graph.SpanningTree@H_301_9@类实现的。要建立结点-边对象,我们使用addNode@H_301_9@和addEdgeFor@H_301_9@方法,具体如何实现这里就不作介绍了。@H_301_9@@H_301_9@

在实际操作中,我们并不需要总是手动地迁移可视化的数据。要为一个加载进来的数据集建立Data@H_301_9@对象以便用来进行可视化,我们常常可以使用一些方便的方法Data.fromArray()@H_301_9@函数可以把一个以ActionScript@H_301_9@对象数组方式存储的列表数据建立成一个Data@H_301_9@对象,而Data.fromDataSet()@H_301_9@方法则可以以同样的方法把一个DataSet@H_301_9@对象建立为一个数据实例。@H_301_9@@H_301_9@

构造一个可视化工程@H_301_9@@H_301_9@

现在让我们来把前面所讲的凑在一起,进行完整的可视化建立工作。一个Visualization@H_301_9@类只能表示一个单独的可视工程,包括可视标记和坐标。要建立一个可视化工程,我们要装载数据集,把数据加到此工程中,并且设立用来决定如何可视化数据的算子。下面是一个例子。先把代码总体浏览一遍,然后认真阅读代码去理解每一部分的功能@H_301_9@@H_301_9@

package {@H_301_9@

    @H_301_9@import flare.data.DataSet;@H_301_9@

    @H_301_9@import flare.data.DataSource;@H_301_9@

    @H_301_9@import flare.scale.ScaleType;@H_301_9@

    @H_301_9@import flare.vis.Visualization;@H_301_9@

    @H_301_9@import flare.vis.data.Data;@H_301_9@

    @H_301_9@import flare.vis.operator.encoder.ColorEncoder;@H_301_9@

    @H_301_9@import flare.vis.operator.encoder.ShapeEncoder;@H_301_9@

    @H_301_9@import flare.vis.operator.layout.AxisLayout;@H_301_9@

 @H_301_9@

    @H_301_9@import flash.display.Sprite;@H_301_9@

    @H_301_9@import flash.events.Event;@H_301_9@

    @H_301_9@import flash.geom.Rectangle;@H_301_9@

    @H_301_9@import flash.net.URLLoader;@H_301_9@

 @H_301_9@

    @H_301_9@[SWF(width="800",frameRate="30")]@H_301_9@

    @H_301_9@public class Tutorial extends Sprite@H_301_9@

   @H_301_9@ @H_301_9@{@H_301_9@

        @H_301_9@private var vis:Visualization;@H_301_9@

 @H_301_9@

        @H_301_9@public function Tutorial()@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@loadData();@H_301_9@

        @H_301_9@}@H_301_9@

 @H_301_9@

        @H_301_9@private function loadData():void@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@var ds:DataSource = new DataSource(@H_301_9@

                @H_301_9@"http://flare.prefuse.org/data/homicides.tab.txt","tab");@H_301_9@

            @H_301_9@var loader:URLLoader = ds.load();@H_301_9@

            @H_301_9@loader.addEventListener(Event.COMPLETE,function(evt:Event):void {@H_301_9@

                @H_301_9@var ds:DataSet = loader.data as DataSet;@H_301_9@

                @H_301_9@visualize(Data.fromDataSet(ds));@H_301_9@

            @H_301_9@});@H_301_9@

        @H_301_9@}@H_301_9@

 @H_301_9@

        @H_301_9@private function visualize(data:Data):void@H_301_9@

        @H_301_9@{@H_301_9@

            @H_301_9@vis = new Visualization(data);@H_301_9@

            @H_301_9@vis.bounds = new Rectangle(0,600,500);@H_301_9@

            @H_301_9@vis.x = 100;@H_301_9@

            @H_301_9@vis.y = 50;@H_301_9@

            @H_301_9@addChild(vis);@H_301_9@

 @H_301_9@

            @H_301_9@vis.operators.add(new AxisLayout("data.date","data.age"));@H_301_9@

            @H_301_9@vis.operators.add(new ColorEncoder("data.cause",Data.NODES,@H_301_9@

                @H_301_9@"lineColor",ScaleType.CATEGORIES));@H_301_9@

            @H_301_9@vis.operators.add(new ShapeEncoder("data.race"));@H_301_9@

            @H_301_9@vis.data.nodes.setProperties({fillColor:0,lineWidth:2});@H_301_9@

            @H_301_9@vis.update();@H_301_9@

        @H_301_9@}@H_301_9@

    @H_301_9@}@H_301_9@

}@H_301_9@

让我们来大致看一下每个方法。结构体很简单,只是调用了一个loadData@H_301_9@方法。让我们沿下面的思路来进行分析: @H_301_9@@H_301_9@

※第一部分:初始化。@H_301_9@@H_301_9@

1、  @H_301_9@@H_301_9@@H_301_9@建立一个新的可视化工程;@H_301_9@@H_301_9@

2、  @H_301_9@@H_301_9@@H_301_9@为这个工程设定边界;@H_301_9@@H_301_9@

3、  @H_301_9@@H_301_9@@H_301_9@为我们的可视化工程设定坐标,并把它加入到显示列表之中。@H_301_9@@H_301_9@

@H_305_1404@※第二部分:指定可视编码。@H_301_9@@H_301_9@

1、  @H_301_9@@H_301_9@@H_301_9@使用一个坐标,把“date”@H_301_9@放在x@H_301_9@轴上,“age”@H_301_9@放在y@H_301_9@轴上;@H_301_9@@H_301_9@

2、  @H_301_9@@H_301_9@@H_301_9@加入一个颜色编码,以便一个结点的边色可以代表“cause@H_301_9@”这个变量;@H_301_9@@H_301_9@

3、  @H_301_9@@H_301_9@@H_301_9@加入一个外形编码,以便一个对象的外形可以表示一个受害人的肤色;@H_301_9@@H_301_9@

4、  @H_301_9@@H_301_9@@H_301_9@设定默认属性@H_301_9@@H_301_9@

5、  @H_301_9@@H_301_9@@H_301_9@最后,调用更新方法@H_301_9@@H_301_9@

更新一个可视化工程@H_301_9@@H_301_9@

一旦一个可视化工程被建立,我们可能会需要更新[3]@H_301_9@它。例如,我们可能想要改变颜色编码来代替对人的性别的可视化。@H_301_9@@H_301_9@

首先,让我们来加入一个新的方法@H_301_9@@H_301_9@

private function colorByGender():void@H_301_9@

{@H_301_9@

       @H_301_9@var color:ColorEncoder = ColorEncoder(vis.operators[1]);@H_301_9@

      @H_301_9@ @H_301_9@color.source = "data.sex";@H_301_9@

       @H_301_9@color.palette = new ColorPalette([0xffff5555,0xff8888ff]);@H_301_9@

      @H_301_9@ @H_301_9@vis.update(new Transitioner(2)).play();@H_301_9@

}@H_301_9@

这个方法中,@H_301_9@@H_301_9@

1、    @H_301_9@@H_301_9@@H_301_9@恢复第二个算子并将它转化为一个ColorEncoder@H_301_9@。@H_301_9@@H_301_9@

2、    @H_301_9@@H_301_9@@H_301_9@为颜色编码器改变源属性以使用“data.sex”@H_301_9@变量。@H_301_9@@H_301_9@

3、    @H_301_9@@H_301_9@@H_301_9@设立一个新的调色板@H_301_9@@H_301_9@

4、    @H_301_9@@H_301_9@@H_301_9@把这些变化通过调用一个含有Transitioner@H_301_9@和两秒钟动画的更新方法动画化。@H_301_9@@H_301_9@

现在我们需要把两个应用程序连接起来以便我们可以交互地触发更新。要做到这一点,把下面的代码加入到结构体中:@H_301_9@@H_301_9@

   @H_301_9@// add a clickable label@H_301_9@

   @H_301_9@var button:TextSprite = new TextSprite("Color by Gender");@H_301_9@

   @H_301_9@addChild(button);@H_301_9@

   @H_301_9@button.x = 710;@H_301_9@

   @H_301_9@button.y = 50;@H_301_9@

   @H_301_9@button.buttonMode = true;@H_301_9@

   @H_301_9@button.addEventListener(MouseEvent.CLICK,function(evt:MouseEvent):void { colorByGender(); });@H_301_9@

这段代码@H_301_9@@H_301_9@

1、    @H_301_9@@H_301_9@@H_301_9@建立了一个新的文本标签@H_301_9@@H_301_9@

2、    @H_301_9@@H_301_9@@H_301_9@把它加入到了程序之中并设定了它的位置;@H_301_9@@H_301_9@

3、    @H_301_9@@H_301_9@@H_301_9@buttonMode@H_301_9@设定为true@H_301_9@;@H_301_9@@H_301_9@

4、    @H_301_9@@H_301_9@@H_301_9@加入了一个当标签被点击时会触发的事件侦听器。@H_301_9@@H_301_9@

为了这些代码能够工作,我们需要在代码顶部再加入几句导入声明:@H_301_9@@H_301_9@

import flash.events.MouseEvent;@H_301_9@

import flare.animate.Transitioner;@H_301_9@

import flare.display.TextSprite;@H_301_9@

import flare.util.palette.ColorPalette;@H_301_9@

现在我们就可以编译并运行这个应用了。单击“Color by Gender@H_301_9@”标签可以使数据的变化按照颜色编码以动画的形式表现。以下是显示结果。@H_301_9@@H_301_9@

@H_301_9@

最后一步@H_301_9@@H_301_9@

上面的几个例子向展示了Flash@H_301_9@和Flare@H_301_9@库的一些基本内容,但是还有很多特性我们在这里尚未涉及。要进一步学习,我们建议你(1@H_301_9@)通过浏览Flare@H_301_9@和Flash@H_301_9@的API@H_301_9@文档来对所有可用的类进行一下感知,(2@H_301_9@)仔细研究一下flare.demo@H_301_9@里展示的几个示例,想想如何把它们应用到其它的可视化工作中。或者,如果能够把整个flare@H_301_9@源代码看一遍,找出其工作的原理,那会对你更有帮助。@H_301_9@@H_301_9@

要帮助你做到上面这一点,这里提供一个对flare.vis@H_301_9@子类的一个概览:@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.axis: @H_301_9@提供坐标,标签和网格线;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.controls: @H_301_9@提供选择、缩放等一系列交互式操作方法@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.data: @H_301_9@用来呈现可视数据元素的可视化对象;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.data.render: @H_301_9@用来绘制DataSprites@H_301_9@的插入式渲染工具;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.events: @H_301_9@包含flare@H_301_9@框架中使用的event@H_301_9@类型;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.legend: @H_301_9@呈现用来描述可视化编码的legends@H_301_9@;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.operator: @H_301_9@用来定义可视化效果的构建模块;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.palette: @H_301_9@颜色、形状和尺寸的调制工具;@H_301_9@@H_301_9@

Ø   @H_301_9@@H_301_9@@H_301_9@flare.vis.util: @H_301_9@一些普遍常用的类集。@H_301_9@@H_301_9@

现在你应该能够对flare.demo@H_301_9@包中的示例有足够的认识和理解了。你可以通过自由地对这些示例进行任何修改、复制和粘贴,来获得对FLASH@H_301_9@和FLARE@H_301_9@的更多理解。@H_301_9@@H_301_9@

 @H_301_9@

Flare@H_301_9@的应用范例@H_301_9@@H_301_9@

Flare@H_301_9@目前在很多地方,尤其在网站中有着十分广泛的应用。@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2010.3.12@H_301_9@@H_301_9@@H_301_9@:@H_301_9@@H_301_9@BBC NEWS@H_301_9@使用flare@H_301_9@来映射网络上的前100@H_301_9@个网站; @H_301_9@@H_301_9@

@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2010.01.29@H_301_9@@H_301_9@@H_301_9@:@H_301_9@flare@H_301_9@被用来帮助ABC News@H_301_9@的Good Morning America@H_301_9@展示美国国务卿希拉里与电视剧《老友记》的关系; @H_301_9@@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2009.09.25@H_301_9@@H_301_9@@H_301_9@: @H_301_9@Slate magazine@H_301_9@使用flare@H_301_9@来呈现变化多端的数据图表; @H_301_9@@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2009.02.20@H_301_9@@H_301_9@@H_301_9@: @H_301_9@Wired Italia@H_301_9@使用Flare@H_301_9@来呈现他们的多媒体内容可视化界面; @H_301_9@@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2009.02.10@H_301_9@@H_301_9@@H_301_9@: @H_301_9@MemeTracker@H_301_9@搜集了160@H_301_9@万主流媒体和博客站点,对其中的用户评论进行了分析,然后用flare@H_301_9@将可视化结果呈现;@H_301_9@@H_301_9@ @H_301_9@@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2008.10.27@H_301_9@@H_301_9@@H_301_9@: @H_301_9@GoodGuide Political Contributions(@H_301_9@《政治贡献指南》)@H_301_9@应用程序使用flare@H_301_9@来可视化地呈现企业对美国政治党派所做出的贡献的数量以及类型;@H_301_9@@H_301_9@ @H_301_9@@H_301_9@

@H_301_9@@H_301_9@

n  @H_301_9@@H_301_9@@H_301_9@2008.04.02@H_301_9@@H_301_9@@H_301_9@: @H_301_9@IBM@H_301_9@可视通信实验室使用flare@H_301_9@来为其Many-Eyes@H_301_9@来建立可视化工程。 @H_301_9@@H_301_9@@H_301_9@

Flare@H_301_9@的发行版本@H_301_9@@H_301_9@@H_301_9@

2010.10.07@H_301_9@@H_301_9@@H_301_9@: @H_301_9@The development version on GitHub@H_301_9@目前对Flash Player 10@H_301_9@有了更好的支持,并且有一些其它的小的改动与变化,但官方发行版本仍然是flare 2009.01.24@H_301_9@;@H_301_9@@H_301_9@@H_301_9@

2009.01.24@H_301_9@@H_301_9@@H_301_9@:@H_301_9@ flare 2009.01.24@H_301_9@发行。这只是对前一版本进行了一些bug@H_301_9@修改和更新的维护版,这是为Flash Player 9@H_301_9@发行的最后一个版本,以后的版本将都针对Flash Player 10@H_301_9@;@H_301_9@@H_301_9@ @H_301_9@@H_301_9@

2008.07.30@H_301_9@@H_301_9@@H_301_9@: @H_301_9@flare 2008.07.29@H_301_9@发行,这是一个重要的发行版本,新加入了很多的特性与结构改进;@H_301_9@@H_301_9@:@H_301_9@ flare 2008.08.08@H_301_9@发行;@H_301_9@@H_301_9@@H_301_9@

 @H_301_9@@H_301_9@

 @H_301_9@@H_301_9@

 @H_301_9@@H_301_9@

 @H_301_9@@H_301_9@

[@H_301_9@参考文献]@H_301_9@@H_301_9@@H_301_9@

[1]@H_301_9@ Flare@H_301_9@官方网站@H_301_9@http://flare.prefuse.org@H_301_9@@H_301_9@@H_301_9@

[2]@H_301_9@百度百科@H_301_9@@H_301_9@@H_301_9@

 @H_301_9@@H_301_9@

[@H_301_9@注释]@H_301_9@@H_301_9@@H_301_9@

[1]scenegraph@H_301_9@。目前在网络上尚找不到此词的统一翻译,一般都直接引用为原英文单词,此处翻译为“场景图”,未发现“场景图”一词的已有定义。@H_301_9@@H_301_9@@H_301_9@

[2]container,@H_301_9@直译为“容器”。不知在此具体如何翻译,简单采用直译。为了防止误解,在下文中,你会看到的“容器”一词,正是“container@H_301_9@”。@H_301_9@@H_301_9@@H_301_9@

[3]update,@H_301_9@更新。这里实际上指的是数据的实时更新,而非我们平时我说的软件更新。下文中很多“更新”都是指“update”@H_301_9@。@H_301_9@@H_301_9@

猜你在找的Flex相关文章