VML+Javascript实现的垂直柱状统计图

之前做项目用到的VML统计图, 项目的周期紧, 匆忙赶了一个出来, 暂时只实现 [ 垂直柱状统计图 ], 之后就再也没有去完善了 :(

VMLChartSample.htm:

<!DOCTYPE HTML public "-//W3C//DTD HTML 4.01 Transitional//EN">

<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<style>
    v\:* { BEHAVIOR: URL(#default#VML) }
    o\:* { BEHAVIOR: URL(#default#VML) }
</style>
<script language="javascript" src="VMLChartFactory.js"></script>
<script>

//创建图表工厂
var chartFactory = new VML_ChartFactory();

function showChart()
{
    //分类与值
    var c = [ "我基本原理", "我基本原理百慕大", "我基本原理在载有", "在载有我在", "在载有基本原理" ];
    var v = [ 4455, 3010.33, 1001.77, 5555, 8999 ];

    //创建一个图表的参数对象
    var p = new VML_ChartParams( 1, document.all("chartPanel"), 600, 350, "ChartTest", c, v );

        //设置柱状图的特有属性.......
        p._FontColor = "#996633";
        
        //取消3D状态
        //p._3D = false;
        
        //显示百分比
        //p._Percent = true;    

    //将图表参数对象传入图表工厂生产出相应的图表
    var chart = chartFactory.Create(p);
    
    //显示图表
    chart.Show();

}

//当窗体加载完成,创建图表
window.attachEvent( "onload", showChart );

</script>
</head>
<body>

<div style="background:#eeeeee;padding:10px;">

<span id="chartPanel"></span>

</div>


</body>
</html>

VMLChartFactory.js:

function window.onerror(sMsg, sUrl, sLine){ alert(sMsg);return true; }

//暂时只实现 [ 垂直柱状统计图 ]

var VML_CHARTTYPE_CLUMN = 1;    //垂直柱状统计图
var VML_CHARTTYPE_BAR     = 2;    //水平柱状统计图
var VML_CHARTTYPE_PIE     = 3;    //饼图


// 统计图类型, 显示图表的容器对象, 图表宽, 图表高(像素),标题,分类名称组,分类数值组
function VML_ChartParams( chartType, objContainer, iWidth, iHeight, strTitle, arrCategories, arrValues )
{
    //颜色
    this._Color1 = [
        "#00ff00","#ff0000","#ff9900","#33cccc","#666699","#993300","#99cc00","#0000E8","#0080C0","#ff0000",
        "#8080FF","#FF8000","#DDDD00","#0080C0","#660099","#990099","#00ff00","#ff0000","#ff9900","#33cccc",
        "#666699","#993300","#99cc00","#0000E8","#0080C0","#ff0000","#8080FF","#FF8000","#DDDD00","#0080C0"
    ]
    this._Color2 = [
        "#d1ffd1","#ffbbbb","#ffe3bb","#cff4f3","#d9d9e5","#ffc7ab","#ecffb7","#8888FF","#37BEFF","#ffbbbb",
        "#B5B5FF","#FFB468","#FFFF8E","#BBE9FF","#DD97FF","#FF86FF","#d1ffd1","#ffbbbb","#ffe3bb","#cff4f3",
        "#d9d9e5","#ffc7ab","#ecffb7","#8888FF","#37BEFF","#ffbbbb","#B5B5FF","#FFB468","#FFFF8E","#BBE9FF"
    ]

    //图表通用属性
    this._Type             = (chartType)? chartType : VML_CHARTTYPE_CLUMN;
    this._Container        = (objContainer)? objContainer : document.body;
    //
    this._Width         = (iWidth)? iWidth : 300;        //默认300px
    this._Height         = (iHeight)? iHeight : 300;        //默认300px
    this._Title            = (strTitle)? strTitle : null ;
    this._Categories    = (arrCategories)? arrCategories : null;
    this._Values        = (arrValues)? arrValues : null;

    //
    this._FontSize        = 12;        //字体大小12像素
    this._FontColor        = "";        //字体颜色
    
    this._Percent        = false;        //显示百分比
    this._PcntColor        = "#996600";    //百分比颜色
    this._PcntSize        = 12;            //百分比字体大小
    
    this._YGTxtWidth    = 50;        //刻度上字体的框宽度
    this._YGTxtHeight    = 22;        //刻度上字体的框高度
    
    this._PaddingTop    = 30;        //顶层空白
    this._PaddingBottm    = 30;        //底层空白
    
    //以下是柱状图的特有属性
    
    //构造函数只提供通用的属性,可以在创建对象后再进行赋值
    
    this._3D            = true;
    this._BgColor        = "";            //整体背景色
    this._CBgColor        = "#9cf";        //图表背景色
    this._CBgLineColor    = "#69f";        //背景线条色
    //
    this._YG             = 5;            //Y轴刻度: 5
    this._ClmThick         = 16;            //柱状厚像素
    this._AxisWeight    = "1pt";        //坐标轴宽度
    this._AxisColor        = "";            //坐标轴颜色
    this._AxisStyle        = "Solid";        //坐标线形

}

//alert( (new VML_ChartParams())._Container );

function VML_ChartFactory( params )
{
    this._Index        = 0;
    this._Params    = (params)? params : null;
    if( this._Params ){ this._Index++; }
    
    this.Create = function( params )
    {
        this._Params = params;
        this._Index++;
        
        switch( this._Params._Type )
        {
            case VML_CHARTTYPE_CLUMN:
                return new VML_ClumnChart( params, this._Index );
                break;
            case VML_CHARTTYPE_BAR:
                return null;
            case VML_CHARTTYPE_PIE:
                return null;
            default:
                return null;
        }
    };    
}

function VML_ClumnChart( params, _Index )
{
    if( !params ) return null;

    var _MUL = 100;        //倍数
    
    this._params = params;
    
    var _Color1 = params._Color1;
    var _Color2 = params._Color2;
    
    var _Title     = params._Title;
    var _Ctgs     = params._Categories;
    var _Vlus     = params._Values;
    
    var _FontSize        = params._FontSize;
    var _FontColor        = params._FontColor;
    
    var _Percent        = params._Percent;
    var _PcntColor        = params._PcntColor;
    var _PcntSize        = params._PcntSize;
    
    var _YGTxtWidth        = params._YGTxtWidth;
    var _YGTxtHeight    = params._YGTxtHeight;
    
    var _PaddingTop        = params._PaddingTop;
    var _PaddingBottm    = params._PaddingBottm;

    var _3D                = params._3D;
    var _BgColor        = params._BgColor;
    var _CBgColor        = params._CBgColor;
    var _CBgLineColor    = params._CBgLineColor;
    
    var _YG                = params._YG;
    var _ClmThick        = params._ClmThick;
    var _AxisWeight        = params._AxisWeight;
    var _AxisColor        = params._AxisColor;
    var _AxisStyle        = params._AxisStyle;
    
    var _Width             = params._Width;
    var _Height         = params._Height;
    
    ////////////////
    var _YGTxtInWH     = _YGTxtWidth * _MUL;
    var _YGTxtInHH     = _YGTxtHeight * _MUL;

    var _OutWH     = 0;
    var _OutHH     = 0;
    var _InWH     = 0;
    var _InHH     = 0;
    var _CSL    = 0;
    var _CST    = 0;
    
    var _MaxValue = 0;
    var _ClmSpacing = 0;
    
    var _YGvalue = 0;
    var _YGSpacing = 0;

    ///////////////////////
        
    try
    {
        for(var i=0; i< _Vlus.length; i++)
        {
            _Vlus[i] = parseFloat( _Vlus[i] )
            if( isNaN(_Vlus[i]) ){ throw "分类值必须是数值型或数字型字符串"; }
            if( _Vlus[i] > _MaxValue )_MaxValue = _Vlus[i];
        }
    
        var _Margin = 10 * _MUL;
        
        var _PDTOP    = _PaddingTop * _MUL;
        var _PDBOM    = _PaddingBottm * _MUL;
        
        _CSL     = _Margin ;        //图表起始的横坐标
        _CST    = _Margin ;        //图表起始纵坐标
        
        _OutHH     = _Height * _MUL;                //总高度( 图表最大高度 + 间隔宽度 )
        _OutWH     = _Width * _MUL;                //总宽度( 原始大小放大 )
            
        _InHH     = _OutHH - _PDBOM - _Margin * 2 ;    //图表最大高度
        _InWH    = _OutWH - _YGTxtInWH - _Margin * 2 ;        //图表最大宽度= 总宽 - 刻度文字宽度

        
        var _MaxYGD = GetVmlMaxYGD(_MaxValue);    
        
        _YGvalue      = _MaxYGD/_YG;                    //刻度间隔值
        _YGSpacing      = (_InHH - _PDTOP)/_YG;        //刻度间隔(放大)
        
        //alert( _PosLeftStart );
    }
    catch(e)
    {
        alert(e);
        return null;
    }
    
    //
    var oGroup = document.createElement("v:group");
        oGroup.id = "VML_CHART_GROUP_" + _Index;
        oGroup.style.position     = "relative";
        oGroup.style.width         = _Width + "px";
        oGroup.style.height     = _Height + "px";
        oGroup.style.backgroundColor  = _BgColor;
        oGroup.coordsize = _OutWH + "," + _OutHH;
        //oGroup.coordorigin = _CSL + "," + ( _CST + _InHH );
        
    var sMarkID = "VML_" + _Index ;
    
    var _RectSL = _CSL + _YGTxtInWH;
    var _RectST = _CST;
    
    var strBgRect = "<!--[if gte vml 1]>" +
                    "<v:rect id='" + sMarkID + "_x0001_s1' title='" + _Title + "' " +
                    "style='position:absolute;z-index:-1;left:" + (_RectSL) + ";top:" + (_RectST) + ";" +
                    "width:" + _InWH + ";height:" + _InHH + ";' " +
                    "fillcolor='" + _CBgColor + "' stroked='f'>" +
                    "<v:fill rotate='t' angle='-45' focus='100%' type='gradient'/>" +
                    "</v:rect>" +
                    "<![endif]-->";

    var strAxis = "" +
                    "<!--[if gte vml 1]>" +
                    "<v:line id='" + sMarkID + "_x0002_s1' " +
                    "style='position:absolute;z-index:-1;' "+
                    "from='" + (_RectSL + 0) + "," + (_RectST) + "' to='" + (_RectSL + 0) + "," + ( _RectST + _InHH ) + "'>" +
                    "<v:stroke StartArrow='Open'/>" +
                    "</v:line>" +
                    "<![endif]-->" +
                    "<!--[if gte vml 1]>" +
                    "<v:line id='" + sMarkID + "_x0003_s2' alt='' " +
                    "style='position:absolute;z-index:-1;' "+
                    "from='" + (_RectSL + 0) + "," + ( _RectST + _InHH + 0 ) + "' to='" + ( _RectSL + _InWH ) + "," + ( _RectST + _InHH + 0 ) + "'>" +
                    "<v:stroke EndArrow='Open'/>" +
                    "</v:line>" +
                    "<![endif]-->"
    //
    var strBgLine = "";
    var strYGText = "";
    
    var _NowYGvalue = 0;
    
    var _TKW = (_ClmThick/2) * _MUL;
    
    var _YGTxtSL = _CSL;
    var _YGTxtST = _CST + _PDTOP;
    
    var _PL1 = _CSL + _YGTxtInWH/2 ;
    var _PT1 = _CST + _PDTOP;
    
    var _PL2 = _PL1 + _YGTxtInWH/2 ;
    var _PT2 = _PT1 + _YGSpacing ;
    
    var _PL3 = _PL2 + _TKW ;
    var _PT3 = _PT2 - _TKW;
    
    var _PL4 = _PL3 + _InWH - _TKW ;
    var _PT4 = _PT3;
        
    for( var i=0; i<_YG; i++ )
    {
        _NowYGvalue = _YGvalue * (_YG - i);        //刻度值

        strBgLine += "<!--[if gte vml 1]><v:line id='"+ sMarkID +"_x0004_s"+ i +"' alt='' style='position:absolute;z-index:-1' from='" + (_PL1) + "," + (_PT1) + "' to='" + (_PL2) + "," + (_PT1) + "' /><![endif]-->";
        strBgLine += "<!--[if gte vml 1]><v:line id='"+ sMarkID +"_x0005_s"+ i +"' alt='' style='position:absolute;z-index:-1' from='" + (_PL2) + "," + (_PT2) + "' to='" + (_PL3) + "," + (_PT3) + "' strokecolor='" + _CBgLineColor + "'/><![endif]-->";
        strBgLine += "<!--[if gte vml 1]><v:line id='"+ sMarkID +"_x0006_s"+ i +"' alt='' style='position:absolute;z-index:-1' from='" + (_PL3) + "," + (_PT3) + "' to='" + (_PL4) + "," + (_PT4) + "' strokecolor='" + _CBgLineColor + "'/><![endif]-->";
        //
        strYGText += "<!--[if gte vml 1]>" +
                "<v:shape id='"+ sMarkID +"_x0007_s"+ i +"' alt='' " +
                "style='position:absolute;z-index:1;" +
                "left:" + (_PL1-_YGTxtInWH/2) + ";top:" + _PT1 + ";width:" + _YGTxtInWH + ";height:" + _YGTxtInHH + ";'>" +
                "<v:textbox inset='0,0,0,0'>" +
                "<table cellspacing='3' cellpadding='0' width='100%' height='100%'>" +
                "<tr><td align='right' style='font-size:12px;color:;'>" + _NowYGvalue + "</td></tr>" +
                "</table>" +
                "</v:textbox>" +
                "</v:shape>" +
                "<![endif]-->";
        //alert(strBgLine);
        
        _PT1 = _PT2;
        _PT2 = _PT2 + _YGSpacing;
        _PT3 = _PT2 - _TKW;
        _PT4 = _PT3;
    }
    //
    
    var strLeftLn = "<!--[if gte vml 1]><v:line id='"+ sMarkID +"_x0008_s1' alt='' style='position:absolute;z-index:-1' from='" + (_CSL + _YGTxtInWH + _TKW ) + "," + (_CST) + "' to='" + ((_CSL + _YGTxtInWH + _TKW )) + "," + (_CST + _InHH - _TKW ) + "' strokecolor='" + _CBgLineColor + "'/><![endif]-->";
    
    //
    var strClumns = "";
    var strCtgsText = "";
    var strVlusText = "";
    var strPcntText = "";
    
    var    _ClmSL = _CSL + _YGTxtInWH + _TKW;    //柱状起始坐标Left
    var _ClmST = _CST + _InHH;                //柱状起始坐标Top
    
    var _CPWH = (_InWH - _ClmSL) / _Vlus.length;
    var _CCWH = (_InWH - _ClmSL) / (_Vlus.length*2)
        
    //_MaxYGD
    
    for( var i=0;i<_Vlus.length;i++ )
    {
        var _CurPcnt =    _Vlus[i]/_MaxYGD;
        var _CurrCHH = (_InHH - _PDTOP) * _CurPcnt ;
        var strPcnt = (_CurPcnt * 100 ).toFixed(2) + "%";

        var _Left1    = _ClmSL + ( i * _CPWH ) + _CCWH;
        var _Left2     = _ClmSL + ( i * _CPWH ) + _CCWH/2;
        var _Left3    = _ClmSL + ( i * _CPWH );
        
        var strCLUMN3D = (_3D)? "<o:extrusion v:ext='view' backdepth='13pt' color='" + _Color1[i] + "' on='t'/>" : "";
        
        strClumns += "<v:rect id='"+ sMarkID +"_x0009_s"+ i +"' style='flip:x;z-index:1'  title='" + strPcnt + "' " +
                    "fillcolor='" + _Color1[i] + "' " +
                    "style='position:absolute;left:" + _Left1 + ";top:" + (_ClmST - _CurrCHH)   + ";" +
                    "width:" + _CCWH + ";height:" + _CurrCHH + ";' >" +
                    "<v:fill color2='" + _Color2[i] + "' rotate='t' type='gradient'/>" +
                    strCLUMN3D +
                    "</v:rect>";
                    
        //文字框高度
        var _FontBoxHH = _PDBOM;
                
        strCtgsText += "" +
                    "<v:shape id='"+ sMarkID +"_x00010_s"+ i +"' alt='' " +
                    "style='position:absolute;z-index:1;" +
                    "left:" + _Left2 + ";top:" + _ClmST + ";width:" + _CPWH + ";height:" + _FontBoxHH + ";'>" +
                    "<v:textbox inset='0,0,0,0'>" +
                    "<table cellspacing='3' cellpadding='0' width='100%' height='100%'>" +
                    "<tr><td align='center' style='font-size:" + _FontSize +"px;color:" + _FontColor + ";'>" + _Ctgs[i] + "</td></tr>" +
                    "</table>" +
                    "</v:textbox>" +
                    "</v:shape>";
                    
        strVlusText += "" +
                    "<v:shape id='"+ sMarkID +"_x00011_s"+ i +"' alt='' " +
                    "style='position:absolute;z-index:1;" +
                    "left:" + _Left1 + ";top:" + (_ClmST - _CurrCHH - _FontBoxHH ) + ";" +
                    "width:" + _CCWH + ";height:" + _FontBoxHH + ";'>" +
                    "<v:textbox inset='0,0,0,0'>" +
                    "<table cellspacing='3' cellpadding='0' width='100%' height='100%'>" +
                    "<tr><td align='center' style='font-size:" + _FontSize +"px;color:" + _FontColor + ";'>" + _Vlus[i] + "</td></tr>" +
                    "</table>" +
                    "</v:textbox>" +
                    "</v:shape>";
                    
        strPcntText += "" +
                    "<v:shape id='"+ sMarkID +"_x00011_s"+ i +"' alt='' " +
                    "style='position:absolute;z-index:2;" +
                    "left:" + _Left1 + ";top:" + (_ClmST - (_CurrCHH + _FontBoxHH)/2 ) + ";" +
                    "width:" + _CCWH + ";height:" + _FontBoxHH + ";'>" +
                    "<v:textbox inset='0,0,0,0'>" +
                    "<table cellspacing='3' cellpadding='0' width='100%' height='100%'>" +
                    "<tr><td align='center' style='font-size:"+ _PcntSize +"px;color:" + _PcntColor + ";'><B>" + strPcnt + "</B></td></tr>" +
                    "</table>" +
                    "</v:textbox>" +
                    "</v:shape>";
    }
    
    oGroup.innerHTML = strBgRect + strAxis + strBgLine + strYGText + strLeftLn + strClumns + strVlusText + strCtgsText ;

    if( _Percent ){    oGroup.innerHTML += strPcntText ;    }
    
    
    
    //
    this.Show = function(){
        this._params._Container.appendChild(oGroup);
    };
    
}

function GetVmlMaxYGD( v )
{
    v = parseFloat(v);
    var iv = Math.round(v);
    if( isNaN(v) ){ throw " v isNaN";}
    
    var sZero = "0000000000000000000000000";
    
    var sv = iv.toString();
    var ivLen = iv.toString().length;
    var iINT  = parseInt("1" + sZero.substr(0,ivLen-1) );
    var iMaxV = parseInt( sv.substr(0,1) );
    var iNewV = 0;
    
    if( (v%iINT)< iINT * 0.5 )
    {
        iNewV = ( iMaxV + 0.5 ) * iINT;
    }
    else
    {
        iNewV = ( iMaxV + 1 ) * iINT;
    }
    return iNewV;
}
//GetVMLGdNum( 445 );

评论: 1 | 引用: 0 | 查看次数: 7110
发表评论
登录后再发表评论!