HTML5簡單圖表插件

最近選修了一門web信息選修課,期末要交一個小項目,原本是想說作個小遊戲的,但想一想最後仍是選擇作了這個jquery插件。網上已經有不少相似的插件了,固然也遠比我這個好得多,但好歹個人代碼雖然有點亂,至少容易看得懂(我本身是這麼天真的認爲的(´・ω・`)!),並且也好久沒來寫過文章,因此就發來獻醜了(つд⊂)!!javascript

好的,廢話就講到這裏了,先簡單講一下個人思路:css

圖表插件的最主要部分就是: 如何將數據轉換成canvas上的座標,其次纔是經過繪畫來展示它。
但一個圖表插件好很差用,我我的以爲是它的輔助計算功能和糾錯能力了,但這個太麻煩,並且我我的能力也有限,因此這裏也沒怎麼弄。html

我在寫的過程當中也遇到了一些問題:好比說canvas怎麼畫出一個扇形等等,這些問題由於之前寫的少就沒遇到過,如今也是學習到了,與其說寫一些小插件是一個考驗本身的過程,我更以爲像一個學習的過程,一些之前本身沒遇到的問題在這裏就可能遇到,因此說多寫果真是有好處的。java

參考資料:http://www.clanfei.com/2014/12/1745.html (扇形如何繪製)jquery

《HTML5 Canvas核心技術 圖形、動畫與遊戲開發》----David Geary (這是一本很好的書額)linux

演示地址:我是demoweb

下載地址:點我下載canvas

圖片展現(4種類型):app

「line-number」:dom

圖片描述

「line-string」:

圖片描述

"cylindricality":

圖片描述

"circle":

圖片描述

HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
<title>dataAnalysis</title>
</head>
<body>
<!---->
<div class="content" style="width:800px;height:600px;">

</div>
<script type="text/javascript" src="js/main.js"></script>
<script type="text/javascript">
    $('.content').dataAnalysis({
        isControl:true
    });
</script>
</body>
</html>

canvas和其餘標籤是經過js自動生成的,由於這樣能夠省了插件使用的不少步驟,canvas的大小和包裹元素的大小一致,這裏是和.content的大小一致。由於對canvas設置了Id,並且當時開寫的時候也沒考慮頁面多個地方調用的狀況,因此插件只能在頁面調用一次,等寫完的時候已經不想再去改了,因此就一直放在了這裏。

CSS

style.css 樣式重置

/*************reset****************/
html{color:#333;-webkit-text-size-adjust:none;height:100%;min-height:100%;font-family: 'Microsoft Yahei';}
body{height: 100%;min-height:100%;}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
table{border-collapse:collapse;border-spacing:0;}
fieldset,img{border:0;}
address,caption,cite,code,dfn,em,var,optgroup{font-style:inherit;font-weight:inherit;}
del,ins{text-decoration:none;}
li{list-style:none;}
h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
abbr,acronym{border:0;font-variant:normal;}
sup{vertical-align:baseline;}
sub{vertical-align:baseline;}legend{color:#000;}
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
body{font-size:12px;}
a{color: #333333;text-decoration: none;}
a:hover{text-decoration:underline; color:#c00;}

/*font*/
*{
    font-size: 1.05em;
    color: #222;
    font-family: "Microsoft Yahei";
}

main.css

#canvas{
    box-shadow: 0px 1px 4px rgba(0,0,0,0.6);
}

#control-fn{
    padding-top: 10px;
    padding-bottom: 10px;
}

.selector{
    padding: 6px 0px 8px 2px;
}

.selector>span{
    margin-left: 10px;
    margin-right: 3px;
}

.unit{
    margin: 0px 0px 0px 10px;
}

.unit input{
    width: 30px;
    margin-right: 10px;
}

.axis{
    padding: 6px 0px 2px 2px;
}

.axis>input{
    width: 240px;
    outline: none;
    margin-right: 10px;
}

.points{
    padding-bottom: 10px;
    border-bottom: 1px solid #e0e0e0;
}


.points .lName{
    margin: 0px 10px 6px 8px;
    width: 120px;
    text-align: left;
    outline: none;
}

.points .lStyle{
    width: 100px;
}

.points input{
    width: 30px;
    border: none;
    box-shadow: 0px 0px 2px #222;
    text-align: center;
}

.points .cName,.points .cPercent{
    width: 50px;
}

.control{
    margin-top: 10px;
}

.control input{
    width: 24px;
    border: none;
    box-shadow: 0px 0px 2px #222;
    text-align: center;
    margin-left: 6px;
}

.control>div{
    display: inline-block;
    margin-left: 2px;
    margin-right: 20px;
}

.control>div:last-child{
    float: right;
    margin-right: 0px;
}

.control button,.axis-create{
    border: none;
    padding: 4px 14px;
    background:#18B4D5;
    outline: none;
    color: #fff;
    font-weight: 700;
    box-shadow: 0px 1px 5px rgba(0,0,0,0.7);
}

JS代碼

插件初始化設置,以及數據的格式,因爲本插件就提供了四種簡單的圖表類型,數據格式也是有區別的:

var dataAnalysis = function(ele,opt){
    this.el = ele;
    this.defaults = {
        isControl : false,
        bathSpace : 30, //座標偏移
/*        data : {
            type : "line-number",
            horizontal: [0,5,10,15,20,25],,, //橫座標
            vertical  : [0,10,20,30,40,50,60],  //縱座標
            horiUnit : "分鐘", //橫座標單位
            vertUnit : "人",   //縱座標單位
            title    : "圖書館週末人流量", //圖表標題
            project : [
                {
                    name : "China",
                    style: "#66ccff",
                    points:[[0,10],[13,20],[15,50],[17,10],[25,20]]
                },
                {
                    name : "Jppan",
                    style: "#F5601F",
                    points:[[5,20],[10,22],[15,30],[17,40],[25,60]]
                }
            ]
        }
*/
/*        data : {
            type : "line-string",
            horizontal: ["1月","2月","3月","4月","5月","6月"], //橫座標
            vertical  : [0,10,20,30,40,50,60],  //縱座標
            title    : "2015年每個月得獎人數", //圖表標題
            project : [
                {
                    name : "China",
                    style: "#66ccff",
                    points:[["1月",10],["2月",20],["3月",50],["4月",10],["5月",20],["6月",15]]
                },
                {
                    name : "Jppan",
                    style: "#F5601F",
                    points:[["1月",20],["2月",22],["3月",30],["4月",40],["5月",60],["6月",16]]
                }
            ]
        }
*/
/*        data : {
            type : "cylindricality",
            horizontal: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"], //橫座標
            vertical  : [0,10,20,30,40,50,60],  //縱座標
            title    : "2015年每個月得獎人數", //圖表標題
            project : [
                {
                    name : "China",
                    style: "#66ccff",
                    points:[["1月",10],["2月",20],["3月",50],["4月",10],["5月",20],["6月",15],
                    ["7月",10],["8月",20],["9月",50],["10月",10],["11月",20],["12月",15]]
                },
                {
                    name : "Jppan",
                    style: "#F5601F",
                    points:[["1月",20],["2月",60],["3月",20],["4月",30],["5月",40],["6月",10],
                    ["7月",20],["8月",20],["9月",40],["10月",50],["11月",10],["12月",15]]
                },
                {
                    name : "US",
                    style: "#F52C9D",
                    points:[["1月",30],["2月",30],["3月",40],["4月",50],["5月",60],["6月",15],
                    ["7月",10],["8月",10],["9月",20],["10月",30],["11月",40],["12月",15]]
                }
            ]
        }
*/
        data : {
            type : "circle",
            title    : "2015年GDP所佔比預測", //圖表標題
            project : [
                {
                    name : "China",
                    style: "#66ccff",
                    percent: 20
                },
                {
                    name : "Jppan",
                    style: "#F5601F",
                    percent: 10
                },
                {
                    name : "US",
                    style: "#F52C9D",
                    percent: 25
                },
                {
                    name : "Others",
                    style: "#A2BC1D",
                    percent: 45
                }
            ]
        }
    };
    this.options = $.extend({},this.defaults,opt);
};

初始化調用:

init : function(){
        this.angle = 0; // 記錄圓形統計圖角度
        this.errorExist = false; //記錄是否存在錯誤

        this.eleCreate().canvasCreate();
        //是否顯示控制元件
        if(this.options.isControl){
            this.eleCreate().controlEleCreate();
            this.elEvent(); //事件初始化
        } else {
            var opt = this.options;
            this.handing(opt); //繪製開始
        }
    }

繪製:

handing : function(opt){
        this.canvasAll().canvasInit();

        if(opt.data.type!="circle") //非圓形統計圖時
        this.canvasAll().canvasAxis(opt.data.horizontal,opt.data.vertical);

        for(var i=0,j=opt.data.project.length;i<j;i++)
        {
            var pro = opt.data.project[i],
                len = opt.data.project.length,
                pos = (i+1) * opt.bathSpace;
            this.dataHandling().nameHanding(pro.name,(opt.data.title || ""),pro.style,pos);

            if(opt.data.type!="circle")
            this.dataHandling().pointsHanding(pro.points,pro.style,len,i);
            else
            this.dataHandling().circleHanding(pro.percent,pro.style,i);
        }

        //錯誤檢測
        if(this.errorExist)
        {
            var cv = $('#canvas')[0],
                ct = cv.getContext('2d');
            ct.clearRect(0,0,cv.width,cv.height);
            return;
        }
    }

一些dom的操做和標籤生成,當不須要在頁面建立輔助元件的時候,只建立canvas並直接繪製,當須要的時候,建立輔助元件和canvas,但並不直接繪製,也就是isControl:true 的時候,代碼中輸入數據是沒效果的。

eleCreate : function(){
        var $el = $(this.el);
        var dataAna = this;
        var ec = {
            canvasCreate:function(){
                var canvas = document.createElement('canvas');
                var $width = $el.width(),
                    $height= $el.height();

                canvas.width = $width;
                canvas.height= $height;
                canvas.id     = "canvas";


                dataAna.addToHtml($el,canvas);
            },

            controlEleCreate:function(){
                var temp = '<div id="control-fn">'+
                            '<div class="points">'+
                            '</div>'+
                            '<div class="selector"><select>'+
                            '<option selected="selected">請選擇</option>'+
                            '<option value="line-number">折線圖(數字)</option>'+
                            '<option value="line-string">折線圖(橫座標爲字符)</option>'+
                            '<option value="cylindricality">柱狀圖</option>'+
                            '<option value="circle">圓形圖</option>'+
                            '</select>'+
                            '<span>圖表標題:</span><input type="text" class="cTitle"/>'+
                            '<span class="unit"><span>橫座標單位:</span><input type="text" class="horiUnit"/>'+
                            '<span>縱座標單位:</span><input type="text" class="vertUnit"/></span>'+
                            '</div>'+
                            '<div class="axis">'+
                            '<input type="text" placeholder="請按順序輸入橫座標,以「,」分隔" class="hori"/>'+
                            '<input type="text" placeholder="請按順序輸入縱座標,以「,」分隔" class="vert"/>'+
                            '<button class="axis-create">生成座標</button>'+
                            '</div>'+
                            '<div class="control">'+
                            '<div>'+
                            '<button id="add">增長</button>'+
                            '<input type="text" placeholder="1" id="point-num">'+
                            '<span>個點</span>'+
                            '</div>'+
                            '<div>'+
                            '<button id="do">生成</button>'+
                            '</div>'+
                            '</div>'+
                            '</div>';

                dataAna.addToHtml($el,temp);
            },

            pointsPositionCreate:function(num){
                if(!num || num=="") num = 0;
                num = num>=20?20:num;
                var temp = "";

                if(dataAna.options.data.type!="circle")
                {
                    temp = '<div><em>名稱:</em><input type="text" placeholder="Zhang" class="lName"><em>顏色:</em><input type="text" placeholder="#ccffee" class="lStyle"></div>';
                    for(var i=1,j=num;i<=j;i++){
                        temp+='<span><em>'+i+'.</em>( <input type="text" placeholder="0"> , <input type="text" placeholder="0"> )</span>';
                    }
                }
                

                if(dataAna.options.data.type=="circle"){
                    for(var i=1,j=num;i<=j;i++){
                        temp+='<span><em>'+i+'.</em>(名稱:<input type="text" placeholder="ABC" class="cName">,所佔比:<input type="text" placeholder="0" class="cPercent">%,顏色:<input type="text" placeholder="#000" class="cStyle"></span>)。';
                    }
                }
                

                var $points = $('.points');
                $points.html("");

                dataAna.addToHtml($points,temp);
            }
        };

        return ec;
    },

    addToHtml : function($wrapElement,ele){
        $wrapElement.append(ele);
    },

事件的處理,主要是輔助功能的事件處理。

elEvent : function(){
        var $el = $(this.el);
        var dataAna = this;
        var cv = $('#canvas')[0],
            ct = cv.getContext('2d');

        evInit();

        function evInit(){
            $('.axis').hide();
            $('.control').hide();
            $('.unit').hide();

            domControl();
            axisCreate();
        }
        
        function addPoints(){
            $('#add').off('click').on('click',function(e){
                var num = $("#point-num").val();
                dataAna.eleCreate().pointsPositionCreate(num);
            });
        }

        function domControl(){
            $('.selector>select').on('change',function(e){
                var val = $(this).val();
                dataAna.options.data.type = val;

                $('.unit').hide();
                $('.axis').show();
                $('.control').hide();
                $('.points').html("");
                $('.axis>input').val("");
                ct.clearRect(0,0,cv.width,cv.height);
                dataAna.options.data.project.length = 0;

                if(val=="line-number")
                $('.unit').show();

                if(val=="circle")
                {
                    $('.axis').hide();
                    $('.control').fadeIn(200);
                }

                addPoints();
                buildImage();
            });
        }

        function axisCreate(){
            $('.axis-create').off('click').on('click',function(e){
                var horiaxis = $('.hori').val(),
                    vertaxis = $('.vert').val();

                if(!horiaxis || !vertaxis)
                return;


                dataAna.options.data.horizontal = horiaxis.split(',');
                dataAna.options.data.vertical    = vertaxis.split(',');

                var hori = dataAna.options.data.horizontal,
                    vert = dataAna.options.data.vertical;

                for(i=0,j=vert.length;i<j;i++){
                    vert[i] = Number(vert[i]);
                }

                if(dataAna.options.data.type=="line-number")
                for(i=0,j=hori.length;i<j;i++)
                {
                    hori[i] = Number(hori[i]);
                }

                $('.control').fadeIn(200);
            });
        }

        function buildImage(){
            $('#do').off('click').on('click',function(e){
                var length = $('.points>span').length;
                if(length==0)
                return;
                var x,y,z;
                var pro = dataAna.options.data.project;
                dataAna.options.data.title = $('.cTitle').val()?$('.cTitle').val():"";

                var len = pro.length;

                pro[len] = {};
                pro[len].points = new Array();

                for(var i=0,j=length;i<j;i++)
                {
                    x = $('.points>span').eq(i).find('input').eq(0).val();
                    y = $('.points>span').eq(i).find('input').eq(1).val();

                    if(!x || !y){
                        alert("請肯定因此點座標均填寫完成!");
                        pro.length = 0;
                        return;
                    }

                    if(dataAna.options.data.type!="circle")
                    {
                        if(dataAna.options.data.type=="line-number")
                        {
                            x = Number(x);
                            dataAna.options.data.vertUnit = $('.vertUnit').val()?$('.vertUnit').val():"";
                            dataAna.options.data.horiUnit = $('.horiUnit').val()?$('.horiUnit').val():"";
                        }

                        pro[len].points[i] = new Array();
                        pro[len].points[i][0] = x;
                        pro[len].points[i][7] = Number(y);
                        pro[len].name = $('.lName').val()?$('.lName').val():"未知";
                        pro[len].style = $('.lStyle').val()?$('.lStyle').val():"#66ccff";
                    } else {
                        pro.length = j;
                        pro[i] = {};
                        var z = $('.points>span').eq(i).find('input').eq(2).val();
                        pro[i].name = x?x:"未知";
                        pro[i].style = z?z:"#5cc3de";
                        pro[i].percent = Number(y)?Number(y):"";
                    }    
                }

                if(dataAna.options.data.type=="cylindricality" || dataAna.options.data.type=="circle")
                {
                    var cv = $('#canvas')[0],
                        ct = cv.getContext('2d');

                    ct.clearRect(0,0,cv.width,cv.height);
                }

                dataAna.handing(dataAna.options);
            });
        }
        
    },

canvas繪製功能----這裏是屬於主要部分的功能了,包括canvas網格初始化和座標系的初始化等等,以及提供畫線,圓,扇形,文字,方形的功能。

canvasAll : function(){
        var dataAna = this;
        var $el = $(this.el);
        var cv = $('#canvas')[0],
            ct = cv.getContext('2d');

        var $width = $('#canvas').width(),
            $height= $('#canvas').height();

        var bathSpace = this.options.bathSpace;

        var ev = {
            canvasInit : function(){
                var space = 10;
                var lenX = Math.floor($width/space),
                    lenY = Math.floor($height/space);

                for(var i=1,j=lenX;i<=j;i++)
                {
                    var x = i * space;
                    dataAna.canvasAll().canvasDraw.drawLine(x,0,x,$height,"#E7E7E7");
                }

                for (var i = 1,j=lenY; i <= j; i++) {
                    var y = i * space;
                    dataAna.canvasAll().canvasDraw.drawLine(0,$height-y,$width,$height-y,"#E7E7E7");
                };

            },

            canvasAxis : function(hor,ver){
                if(dataAna.options.data.type=="cylindricality" && hor[0]!=0)
                {
                    hor.reverse();
                    hor.push(0);
                    hor.reverse();
                }

                var lenHor = hor.length,
                    lenVer = ver.length;

                if(lenHor==0 || lenVer==0)
                return;

                var    bathLength= 10;

                //hori
                dataAna.canvasAll().canvasDraw.drawLine(bathSpace,$height-bathSpace,$width,$height-bathSpace,"#000000");
                //畫X座標點
                for(var i = 0;i<lenHor;i++)
                {
                    //錯誤檢測
                    dataAna.errorHanding("橫座標",hor[i]);

                    var x = bathSpace + (i / lenHor)*($width-bathSpace);
                    dataAna.canvasAll().canvasDraw.drawLine(x,$height-bathSpace,x,$height-bathLength-bathSpace,"#000000");
                    dataAna.canvasAll().canvasDraw.drawText(hor[i],x,$height-bathSpace/2,"14px tohoma");
                }
                
                //vert
                dataAna.canvasAll().canvasDraw.drawLine(bathSpace,$height-bathSpace,bathSpace,0,"#000000");
                //畫Y座標點
                for(var i = 0;i<lenVer;i++)
                {
                    //錯誤檢測
                    dataAna.errorHanding("縱座標",ver[i],"ver");

                    var y = bathSpace + (i / lenVer)*($height-bathSpace);
                    dataAna.canvasAll().canvasDraw.drawLine(bathSpace,$height-y,bathLength+bathSpace,$height-y,"#000000");
                    dataAna.canvasAll().canvasDraw.drawText(ver[i],bathSpace/2,$height-y,"14px tohoma");
                }

                //繪製單位
                if(dataAna.options.data.type=="line-number"){
                    dataAna.canvasAll().canvasDraw.drawText("("+dataAna.options.data.horiUnit+")",$width-bathSpace,$height-bathSpace/2,"12px Microsoft YaHei");
                    dataAna.canvasAll().canvasDraw.drawText("("+dataAna.options.data.vertUnit+")",bathSpace/2,bathSpace/2,"12px Microsoft YaHei");
                }

            },

            canvasDraw  : {
                //畫線(起始X,起始Y,結束X,結束Y,線的顏色)
                drawLine : function(x1,y1,x2,y2,lineStyle){
                    if(!lineStyle || lineStyle=="")
                    lineStyle = "#66ccff";

                    ct.save();
                    ct.strokeStyle = lineStyle;
                    ct.beginPath();
                    ct.moveTo(x1,y1);
                    ct.lineTo(x2,y2);
                    ct.closePath();
                    ct.stroke();
                    ct.restore();
                },
                //畫圓
                drawCircle : function(x,y,startAngle,endAngle,radius,circleStyle){
                    startAngle = startAngle/180 * Math.PI;
                    endAngle   = endAngle/180 * Math.PI;

                    if(!circleStyle || circleStyle=="")
                    circleStyle = "#66ccff";

                    ct.save();
                    ct.beginPath();
                    ct.strokeStyle = "#c0c0c0";
                    ct.fillStyle = circleStyle;
                    ct.arc(x,y,radius,startAngle,endAngle,false);
                    ct.closePath();
                    ct.fill();
                    ct.stroke();
                    ct.restore();

                },
                //繪製文字,其中font是字體,align和base是位置,color是顏色
                drawText : function(text,x,y,font,align,base,color){
                    if(!font || font=="")
                    font = "12px tohoma";

                    if(!align || align=="")    
                    align = "center";

                    if(!base || base =="")
                    base = "middle";

                    if(!color || color == "")
                    color = "#000000";

                    ct.save();
                    ct.font = font;
                    ct.textAlign = align;
                    ct.textBaseline = base;
                    ct.fillStyle = color;
                    ct.fillText(text,x,y);
                    ct.restore();
                },
                
                //繪製方形,style是填充顏色
                drawRect : function(x,y,width,height,style){
                    ct.save();
                    ct.fillStyle = style;
                    ct.fillRect(x,y,width,height);
                    ct.restore();

                    ct.save();
                    ct.beginPath();
                    ct.strokeStyle = "#c0c0c0";
                    ct.rect(x,y,width,height);
                    ct.closePath();
                    ct.stroke();
                    ct.restore();
                },
                
                //繪製扇形,angle 範圍從(0~360)
                drawSector : function(x,y,startAngle,endAngle,radius,sectorStyle){
                    startAngle = startAngle/180 * Math.PI;
                    endAngle   = endAngle/180 * Math.PI;

                    if(!sectorStyle || sectorStyle=="")
                    circleStyle = "#66ccff";

                    ct.save();
                    ct.beginPath();
                    ct.translate(x,y);
                    ct.strokeStyle = "#c0c0c0";
                    ct.fillStyle = sectorStyle;
                    ct.moveTo(0,0);
                    ct.arc(0,0,radius,startAngle,endAngle,false);
                    ct.closePath();
                    ct.fill();
                    ct.stroke();
                    ct.restore();
                }
            }
        };

        return ev;    
    },

數據處理----這裏是計算數據分析並將其轉化成座標的部分,是核心部分,我這裏只是簡單地作了些處理,有不少的侷限性,好比輸入數據必須按照橫座標順序來,其實更好地辦法是專門寫一個糾錯和智能判斷,這樣的體驗更好,但沒辦法,由於本人太懶了( ◔ิω◔ิ)。

dataHandling : function(){
        var dataAna = this,
            $ev = $(this.el),
            opt = this.options,
            bathSpace = opt.bathSpace,
            cv = $('#canvas')[0],
            ct = cv.getContext('2d'),
            $width = $('#canvas').width(),
            $height= $('#canvas').height();

        var ev = {
            nameHanding : function(name,title,style,pos){
                dataAna.canvasAll().canvasDraw.drawText(name,$width-bathSpace,pos,"14px impact","center","top");
                dataAna.canvasAll().canvasDraw.drawRect($width-bathSpace*3,pos,bathSpace,bathSpace/2,style);
                dataAna.canvasAll().canvasDraw.drawText(title,$width/2,6,"24px Microsoft YaHei","center","top","#a0c010");
            },

            circleHanding : function(percent,style,index){
                //錯誤檢測
                dataAna.errorHanding("百分比",percent);

                var x = ($width - bathSpace)/2 + bathSpace,
                    y = ($height - bathSpace)/2;

                var radius = bathSpace*3;

                var angle = dataAna.angle + percent/100*360;

                //繪製扇形
                dataAna.canvasAll().canvasDraw.drawSector(x,y,dataAna.angle,angle,radius,style);
                //繪製數據
                dataAna.canvasAll().canvasDraw.drawRect(bathSpace*(index+1)*2,$height-bathSpace,bathSpace,bathSpace/2,style);
                dataAna.canvasAll().canvasDraw.drawText(percent+"%",bathSpace*(index+1.75)*2,$height-bathSpace*3/4,"13px Microsoft YaHei");

                dataAna.angle = angle;
            },

            pointsHanding : function(points,style,num,index){
                var len = points.length, //點數
                    horizontal = opt.data.horizontal,
                    vertical   = opt.data.vertical,
                    lenHor = horizontal.length || 0,
                    lenVer = vertical.length || 0;


                for(var i=0;i<len;i++){
                    var horVal = points[i][0], //橫座標值
                        vertVal = points[i][8];//縱座標值

                    //錯誤檢測
                    dataAna.errorHanding("點-橫座標",horVal,"hor");
                    dataAna.errorHanding("點-縱座標",vertVal,"ver");

                    switch(opt.data.type){
                        case "line-number" : //全數字折線圖
                        allNumber(i);
                        break;
                        case "line-string" : //橫座標爲字符串的折線圖
                        lineString(i);
                        break;
                        case "cylindricality": //柱形
                        cylindricality(i);
                        break;
                        defaults :
                        alert("error");
                        break;
                    }
                }

                function allNumber(i){
                    horVal = horVal - horizontal[0];
                    vertVal = vertVal - vertical[0];

                    var    x_before = bathSpace + (horVal/(horizontal[lenHor-1]-horizontal[0])) * ($width-bathSpace)*((lenHor-1)/lenHor),
                        y_before = $height -(bathSpace + (vertVal/(vertical[lenVer-1]-vertical[0])) * ($height-bathSpace)*((lenVer-1)/lenVer));
                    
                    //繪製點
                    dataAna.canvasAll().canvasDraw.drawCircle(x_before,y_before,0,360,4,style);

                    //繪製線
                    if(i!=len-1){
                        var x_after = bathSpace + ((points[i+1][0]-horizontal[0])/(horizontal[lenHor-1]-horizontal[0])) * ($width-bathSpace)*((lenHor-1)/lenHor),
                            y_after = $height -(bathSpace + ((points[i+1][9]-vertical[0])/(vertical[lenVer-1]-vertical[0])) * ($height-bathSpace)*((lenVer-1)/lenVer));
                        dataAna.canvasAll().canvasDraw.drawLine(x_before,y_before,x_after,y_after,style);
                    }
                }

                function lineString(i){
                    vertVal = vertVal - vertical[0];

                    var    x_before = bathSpace + ($width-bathSpace)*(i/lenHor),
                        y_before = $height -(bathSpace + (vertVal/(vertical[lenVer-1]-vertical[0])) * ($height-bathSpace)*((lenVer-1)/lenVer));
                    
                    //繪製點
                    dataAna.canvasAll().canvasDraw.drawCircle(x_before,y_before,0,360,4,style);

                    //繪製線
                    if(i!=len-1){
                        var x_after = bathSpace + ($width-bathSpace)*((i+1)/lenHor),
                            y_after = $height -(bathSpace + ((points[i+1][10]-vertical[0])/(vertical[lenVer-1]-vertical[0])) * ($height-bathSpace)*((lenVer-1)/lenVer));
                        dataAna.canvasAll().canvasDraw.drawLine(x_before,y_before,x_after,y_after,style);
                    }
                }

                function cylindricality(i){
                    i = i+1;
                    var w = ($width-bathSpace)*(1/lenHor),//單個座標全部柱形總寬度
                        single_w = (w/num-4);    //單個座標每一個柱形寬度

                    var    x_center = bathSpace + ($width-bathSpace)*(i/lenHor),
                        y = $height -(bathSpace + (vertVal/vertical[lenVer-1]) * ($height-bathSpace)*((lenVer-1)/lenVer));
                    
                    var x_start = x_center - w/2; //使圖形居中

                    
                    var x = x_start + index*single_w;
                    //繪製柱形
                    dataAna.canvasAll().canvasDraw.drawRect(x,y,single_w,$height-y-bathSpace-1,style);
                }
            }
        };

        return ev;
    },

最後是一個簡單的錯誤檢測功能。。(´・ω・`)由於簡單得過度我都很差意思詳細說明了(← ←分明是這傢伙不想寫罷了!)

errorHanding : function(position,val,type){
        var dataAna = this;

        switch(dataAna.options.data.type)
        {
            case "line-number":
            lineNumHanding();
            break;
            case "circle" :
            circleNumHanding();
            break;
            case "line-string":
            lineStrHanding();
            break;
            case "cylindricality":
            cylindHanding();
            break;
        }

        
        function lineNumHanding(){
            if(typeof(val)!="number")
            errorMsg(position);
        }

        function lineStrHanding(){
            if(type=="ver")
            {
                if(typeof(val)!="number")
                errorMsg(position);
            } else if(type == "hor"){
                if(dataAna.options.data.horizontal.indexOf(val)<0)
                errorMsg(position);
            }
        }

        function cylindHanding(){
            if(type=="ver")
            {
                if(typeof(val)!="number")
                errorMsg(position);
            } else if(type == "hor"){
                if(dataAna.options.data.horizontal.indexOf(val)<0)
                errorMsg(position);
            }
        }

        function circleNumHanding(){
            if(typeof(val)!="number")
            errorMsg(position);
        }

        function errorMsg(position){
            var temp = "在"+position+"處出現了錯誤,請檢查您的輸入數據!";
            dataAna.errorExist = true;
            alert(temp);
        }        
    }

以上就是全部的功能代碼了,看上去很複雜,其實很簡單,更完整的請參看下載的源文件,本人只是個小白,各位看官有想法和問題的話,歡迎來討論,之後有想法也會繼續寫文章的,請你們多多支持,謝謝m(_ _)m!!!!

相關文章
相關標籤/搜索