用Flash与C语言制作工程实时数据动态曲线图

宋国志

本文旨在说明如何利用Flash和C语言制作BS模式下的实时数据动态曲线图,现在流行的实时数据曲线图,大都是采用了CS模式的开发语言,BS模式的虽有一些实例,比如google上的股市曲线图,但其实现的方式和流程在网上很少能见到。

其运行时的界面如下,数据实时更新,曲线图从左往右动态移动:


iOS中多条曲线图 如何做多条曲线数据图_function

下面先讲在实现过程中的工作环境以及开发工具进行简单的介绍:

1.         Macromedia Flash Professional 8;

2.         Macromedia Dreamweaver 8;

3.         标准C;

4.         操作系统:Windows,主要用来制作Flash和网页;

5.         操作系统:Linux,用作网站的服务器,安装apache;

6.         apache软件。

假设以上的环境都已经安装完毕,并经测试运行正常,下面就逐步的介绍开发过程:

一.在制作此例前,我假设您已了解以下Flash知识点:

1.使用this.createEmptyMovieClip动态创建MovieClip;

2.使用AS绘制线条或矩形;

3.对Flash中“深度”的理解;

4.使用this.createTextField动态创建文本框

二.正式开始

1.创建一个空白文档,有两个层:

 

iOS中多条曲线图 如何做多条曲线数据图_语言_02

看上图,两个层:

A.script:放置一些脚本;

B.坐标曲线: 放置一个MovieClip,即生成的曲线;

2.按Ctrl+F8新建一个影片剪辑(MovieClip),里面放置一个动态文本框,实例名称为:tips,如下图:


iOS中多条曲线图 如何做多条曲线数据图_flash_03

3.返回场景,将刚才制作的mc坐库中托至场景(放在可视区域外),并且命名为:mouse_mc,如图:

 

iOS中多条曲线图 如何做多条曲线数据图_语言_04

4.按Ctrl+F8新建一个影片剪辑(MovieClip):坐标曲线,有三个层:,如下图:

 

iOS中多条曲线图 如何做多条曲线数据图_function_05

A.     script:放置一些脚本;

B.     文字:放置x,y轴的说明文字;

C.     xy轴: 放置x,y坐标轴;

5.在影片剪辑“坐标曲线”的“xy轴”层上画x,y坐标线:

 

iOS中多条曲线图 如何做多条曲线数据图_c_06

这步就是注意坐标轴的中心点,画在影片剪辑的注册点上,即_x=0,_y=0处;

6.在坐标轴附近,创建二个动态文本框,分别指定变量名为:name_x,name_y,如下图:

 

iOS中多条曲线图 如何做多条曲线数据图_语言_07

这二个文本框用来显示坐标轴的说明文字;

7.     接着在的“script”层的第一帧,加入如下代码:

//载入实时数据的对象

newFollow=new LoadVars();

 

//x,y轴的名称

name_x = "Time(S)";

name_y = "Data";

 

//x轴刻度总长

var xtotal:Number=120;

//y轴刻度总长

var ytotal:Number=100;

 

//存放曲线上点的数组

var point_arr:Array=new Array();

 

//曲线上点的个数,最大为120(表示2分钟)

var numPoints:Number;

numPoints=0;

 

//x轴单位刻度的像素数

var xspace = Math.floor(360/xtotal);

 

//y轴单位刻度的像素数

var yspace = Math.floor(200/ytotal);

 

 

//画X轴刻度

DrawScalX(xtotal);

//画Y轴刻度

DrawScalY(ytotal);

 

//画X轴刻度

function DrawScalX(total:Number) {

    createEmptyMovieClip("scalX_mc", 1);

    scalX_mc.lineStyle(1, 0x6699CC, 80);

    var i:Number;

    for (i=1; i<total+1; i++) {

        if (i%10 == 0) {

            scalX_mc.lineStyle(1, 0x6699CC, 70);

            scalX_mc.moveTo(xspace*i, 0);

            scalX_mc.lineTo(xspace*i, -6);

            CreateText(i, xspace*i-14-5*xspace+15, 5);

        } else {

            scalX_mc.lineStyle(1, 0x6699CC, 30);

            scalX_mc.moveTo(xspace*i, 0);

            scalX_mc.lineTo(xspace*i, -4);

        }

    }

}

 

function DrawScalY(total:Number) {

    createEmptyMovieClip("scalY_mc", 2);

    var i:Number;

    for (i=1; i<total+1; i++) {

        if (i%10 == 5) {

            scalY_mc.lineStyle(1, 0x6699CC, 50);

            scalY_mc.moveTo(0, 0-(yspace*i));

            scalY_mc.lineTo(7, 0-(yspace*i));

        } else if (i%10 == 0) {

            scalY_mc.lineStyle(1, 0x6699CC, 80);

            scalY_mc.moveTo(0, 0-(yspace*i));

            scalY_mc.lineTo(8, 0-(yspace*i));

            CreateText(i, -30, 0-(yspace*i)-9);

        } else {

            scalY_mc.lineStyle(1, 0x6699CC, 30);

            scalY_mc.moveTo(0, 0-(yspace*i));

            scalY_mc.lineTo(4, 0-(yspace*i));

        }

    }

}

 

//建立x,y轴的坐标文本

function CreateText(txt:Number, X:Number, Y:Number) {

   

    var my_txt = createTextField("my_txt"+txt, Math.floor(Math.random()*100000), X, Y, 30, 30);

    my_txt.multiline = false;

    my_txt.wordWrap = true;

    my_txt.selectable = false;

    var my_fmt:TextFormat = new TextFormat();

    my_fmt.color = 0x999999;

    my_fmt.align = "center";

    my_txt.text = txt;

    my_txt.setTextFormat(my_fmt);

}

 

//画曲线

function DrawLine() {

    createEmptyMovieClip("curve_mc", 3);

    //曲线填充色

    curve_mc.beginFill(0xFFFFCC, 50);

    //曲线颜色

    curve_mc.lineStyle(1, 0xFF6600, 100);

    curve_mc.moveTo(0, 0);

   

    for (var i = 0; i<point_arr.length; i++) {

        curve_mc.lineTo(i*xspace, 0-point_arr[i]*yspace);

        DrawCircle((i), 0-(point_arr[i]));

    }

    curve_mc.lineTo(((point_arr.length-1)*xspace), 0);

    curve_mc.lineStyle(1, 0x000000, 0);

    curve_mc.lineTo(0, 0);

    curve_mc.endFill();

    if (point_arr[0])

        _root.cnp="即时数据:"+point_arr[0]+" P/S";

}

 

//构造曲线上点的数组

function display() {

    //曲线上新点的y轴坐标值

    var str:String;

    var i:Number;

   

    newFollow.load("/cgi-bin/getdata.cgi?nocahe="+getTimer());

    newFollow.onLoad=function(){

        str=newFollow.new_point;

       

        for (i=numPoints; i>0; i--) {

            point_arr[i]=point_arr[i-1];

        }

        if (numPoints<120)

            numPoints++;

           

        point_arr[0]=str;

    }

    //画曲线

    DrawLine();

}

 

setInterval(display,1000);

stop();

 

8.返回场景,在场景的第一帧加入如下代码:

//让鼠标提示内容的宽度根据内容的多少自动调整

mouse_mc.tips.autoSize = true;

//页面的编码方式

System.useCodepage = true;

9.将库中的“坐标曲线”影片剪辑拖至场景中,命名为:mc,如下图:

 

iOS中多条曲线图 如何做多条曲线数据图_iOS中多条曲线图_08

10.参数说明:

//载入实时数据的对象

newFollow=new LoadVars();

 

//x,y轴的名称

name_x = "Time(S)";

name_y = "Data";

 

//x轴刻度总长

var xtotal:Number=120;

//y轴刻度总长

var ytotal:Number=100;

 

//存放曲线上点的数组

var point_arr:Array=new Array();

 

//曲线上点的个数,最大为120(表示2分钟)

var numPoints:Number;

numPoints=0;

11.制作Flash影片

导出影片并保存为Real-Time_curve.swf,制作一个网页,将该影片插入到网页中,保存网页为Real-Time_curve.html,然后将该网页和Flash影片一起上传到apache服务器的htdocs目录中。但记得要修改这两个文件的权限,否则在测试的时候会出现无权访问的错误。

三.制作实时数据源

在Linux下编写一个模拟实时数据产生器,其代码如下:

#include <stdio.h>

 

int main(void)

{

    srand((int)time(0));

   

    printf("Content-type: text/html/n/n");

    printf("new_point=%d", rand()%101);

 

    return 0;

}

将代码保存为getdata.c,并将编译后的可执行文件命名为getdata。将可执行的getdata保存到apache服务器的cgi-bin目录中。

在上面的代码中,值得注意的是两个printf语句。第一个printf语句是cgi编程的规范,在这里我不做阐述,可以查阅相关资料做进一步的理解,而第二个printf语句实际上与前面介绍的Flash中的newFollow.load("/cgi-bin/getdata.cgi?nocahe="+getTimer())构成了一个实时数据的通信接口。

四.问题讨论

1.保证数据的实时刷新。在IE浏览器中可能由于缓存的原因而导致Flash无法实时动态的显示,因此在Flash中必须使浏览器每次都从服务器上去读取数据,而不会使用本地的缓存,因此在Flash中调用实时数据源时加上了参数nochae=getTimer(),由于getTimer()在每次调用的时候的值不同,使浏览器认为是调用一个新的程序,这样保证数据的有效性和实时性。

2.动态曲线的刷新频率。setInterval(display,1000)使浏览器每隔一秒钟就调用一次display()函数,重新获取一次数据,然后绘制新的曲线。

3.曲线上点的值保存在一维数组point_arr中,使用该一维数组可以同时体现出曲线上坐标点的位置,数组元素的下标值即为曲线的X坐标值,该下标所对应的数组元素值就为曲线的Y坐标值。由于曲线上总共可以显示120个点的值,也即是2分钟的数据,因此数组的长度也设置为120,2分钟之前的元素没有采用溢出,而是采用的覆盖的方式,这样对系统来说也安全,以免造成内存问题。

4.当然,曲线图的X/Y轴的名称以及轴上的刻度大小都是可以通过html或者其他语言在调用Flash影片时作为参数传递给Flash。

作者:宋国志