canvas繪制經典折線圖(一)


最終效果圖如下:

實現步驟如下:注-引用了jQuery

HTML代碼

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>canvas繪制折線圖</title>
  <script src="scripts/jquery-1.11.3.js"></script>
  <script src="scripts/recordPaint.js"></script>
  <style>
    
  </style>
 </head>
 <script>
    $(function(){
         /*
             * 定義繪制折線圖的關鍵數據(12個月的消費記錄-金額)
             * 封裝函數專門用於繪制折線圖
               recordPaint(Elem,Data)方法
               * Elem - 表示<canvas>元素
               * Data - 表示關鍵數據
          */
         var datas = [1200,2000,3000,500,200,800,1800,2200,2600,1000,600,300];
         recordPaint($("#recordCvs")[0],datas);
    });
 </script>
 <body>
    <div id="recordContent">
        <canvas id="recordCvs" width="600" height="400"></canvas>
    </div>
 </body>
</html>

JS代碼:即HTML中引用的外部JS文件<script src="scripts/recordPaint.js"></script>

/**
 * Created by walker on 2015/11/26.
 * 定義recordPaint()方法
 */
function recordPaint(Elem,Data){
    // 1. 創建畫布對象
    var context = Elem.getContext('2d');
    // 2. 獲取畫布的寬度和高度
    const WIDTH = Elem.width;
    const HEIGHT = Elem.height;
    // 3. 定義坐標軸相對畫布的內邊距
    var padding = 20;//初始化內邊距
    var paddingLeft = 60;//至少大於繪制文字的寬度
    var paddingBottom = 30;//至少大於繪制文字的高度
    // 4. 定義繪制坐標軸的關鍵點的坐標值
    var axisY = {// y軸的起點坐標值
        x : paddingLeft,
        y : padding
    };
    var origin = {// 原點坐標值(x軸與y軸相交點)
        x : paddingLeft,
        y : HEIGHT - paddingBottom
    };
    var axisX = {
        x : WIDTH - padding,
        y : HEIGHT - paddingBottom
    };
    // 5. 繪制坐標軸
    context.beginPath();
    context.moveTo(axisY.x,axisY.y);
    context.lineTo(origin.x,origin.y);
    context.lineTo(axisX.x,axisX.y);
    context.stroke();
    // 6. 繪制坐標軸的箭頭
    context.beginPath();
    context.moveTo(axisY.x-5,axisY.y+10);
    context.lineTo(axisY.x,axisY.y);
    context.lineTo(axisY.x+5,axisY.y+10);
    context.stroke();

    context.beginPath();
    context.moveTo(axisX.x-10,axisX.y-5);
    context.lineTo(axisX.x,axisX.y);
    context.lineTo(axisX.x-10,axisX.y+5);
    context.stroke();

    // 定義折點的x軸值
    var pointsX = [];

    // 7. 繪制坐標軸的刻度(x軸的月份和y軸的金額)
    // x軸的月份
    var month = {
        x : paddingLeft,
        y : HEIGHT - paddingBottom
    }
    // 設置字體
    context.font = "14px 微軟雅黑";
    // 設置垂直對齊
    context.textBaseline = "top";
    for(var i=1;i<=12;i++){
        pointsX[pointsX.length] = month.x;
        // 繪制月份信息
        context.fillText(i+"月",month.x,month.y);
        // 改變每次繪制的x坐標軸的值
        month.x += (axisX.x - origin.x)/12;
    }

    // 繪制y軸的金額
    // 從眾多的關鍵金額中,取到最高金額
    /*
    var datas = [];
    for(index in Data){
        datas[datas.length] = Data[index];
    }
    function sortNumber(a,b){
        return a - b;
    }
    var max = datas.sort(sortNumber)[datas.length-1];
    */
    var max = Math.max.apply(Math,Data);

    var moneyY = (origin.y - axisY.y)/(max/500+1);

    // 定義繪制的坐標值
    var money = {
        x : axisY.x - 5,
        y : axisY.y + moneyY,
        jin : max
    }
    // 設置水品對齊
    context.textAlign = "right";
    // 遍歷"最高值/間隔"次
    for(var i=0;i<max/500;i++){
        // 繪制金額
        context.fillText(money.jin+"元",money.x,money.y);
        // y軸向下移動(增加)
        money.y += moneyY;
        // 金額每次減500
        money.jin -= 500;
    }

    /*
      繪制折線
      * 12個折點的x軸值,對應12個月文字的x軸值
      * 折點的y軸值等於原點的y軸值-折點到原點的距離
        * 折點到原點的距離 = (3000點的y到原點的y的長度)*當前金額/3000
     */
    context.beginPath();
    for(var i=0;i<Data.length;i++){
        // 獲取折點的x和y值
        var pointY = origin.y - (origin.y - (axisY.y + moneyY))*Data[i]/max;
        var pointX = pointsX[i];
        // 繪制折線
        if(i == 0){
            context.textAlign = "left";
            //context.textBaseline = "bottom";
            context.moveTo(pointX,pointY);
        }else{
            context.textAlign = "center";
            context.textBaseline = "bottom";
            context.lineTo(pointX,pointY);
        }
        // 繪制折點的金額
        context.fillText(Data[i],pointX,pointY);
    }
    context.stroke();
    // 繪制12個折點的圓
    for(var i=0;i<Data.length;i++){
        // 獲取折點的x和y值
        var pointY = origin.y - (origin.y - (axisY.y + moneyY))*Data[i]/max;
        var pointX = pointsX[i];
        // 繪制圓
        context.fillStyle = "red";
        context.beginPath();
        context.arc(pointX,pointY,3,0,Math.PI*2);
        context.fill();
    }

}

  總結:每個拐點的坐標值要清晰


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM