最終效果圖如下:
實現步驟如下:注-引用了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(); } }
總結:每個拐點的坐標值要清晰