用highchart的時候發現它是用svg來畫圖的,那麼用canvas來做怎麼樣的。
以前做AS圖表插件的時候,繪制圖畫主要用容器的Graphics對象來繪制,而canvas的context和Graphics一樣,都可以用來繪制圖形。
然後就試著用canvas做了這樣一個東西。
具體實現如下,個人表達能力有問題,各位看官還是看源碼吧,如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/Html; charset=utf-8" /> <title>LineChart</title> </head> <body> <div id="lineChart" style="width: 900px;height: 600px;border: #c9302c"></div> <script src="jquery-1.8.2.min.js"></script> <script src="ChartTest1.JS"></script> <script type="text/Javascript"> $("#lineChart").lineChart("init"); </script> </body> </Html>
ChartTest1.JS源碼如下:
/** * Created by jackyWHJ on 14-2-26. */ (function($) { var canvas,context; var stepXArr=[],stepYArr=[],xStepWidth=0; var xAxisHeight = 0 ,yAxisWidth = 0; var heightVal = 0;//高度值對應數據比例 /** * 畫X軸 * */ var drawXAxis = function (xAxisData) { context.beginPath(); //畫X軸橫線 context.moveTo(yAxisWidth - 6, canvas.height - xAxisHeight); context.lineTo(canvas.width-yAxisWidth,canvas.height - xAxisHeight); //畫刻度、加標簽 var len = xAxisData.length; xStepWidth = (canvas.width-2*yAxisWidth)/len; for(var i = 0;i < len;i++){ //畫刻度,默認刻度高度為6個像素 context.moveTo(yAxisWidth + (i+1)*xStepWidth, canvas.height - xAxisHeight); context.lineTo(yAxisWidth + (i+1)*xStepWidth,canvas.height - xAxisHeight + 6); //畫標簽,默認字體為14個像素 context.font = "normal normal bold 14px 微軟雅黑"; //字體居中在刻度中間 context.fillText(xAxisData[i], yAxisWidth + (i+0.5)*xStepWidth - xAxisData[i].length*14/2, canvas.height - xAxisHeight + 24); //緩存刻度位置,用於畫網格 stepXArr.push(yAxisWidth + (i+1)*xStepWidth); } context.stroke(); } /** * 畫Y軸 * */ var drawYAxis = function(yMax,step) { context.beginPath(); //畫X軸橫線 context.moveTo(yAxisWidth, xAxisHeight); context.lineTo(yAxisWidth,canvas.height - xAxisHeight + 6); //畫刻度、加標簽 var tickWidth = (canvas.height - 2*xAxisHeight )/step; heightVal = (canvas.height - 2*xAxisHeight )/yMax; for(var i = 0;i <= step;i++){ //畫刻度,默認刻度高度為6個像素 context.moveTo(yAxisWidth, canvas.height - xAxisHeight - tickWidth * i); context.lineTo(yAxisWidth - 6,canvas.height - xAxisHeight - tickWidth * i); //畫標簽,默認字體為14個像素 context.font = "normal normal 14px 微軟雅黑"; //字體居中在刻度中間 context.fillText(yMax/step * i, yAxisWidth - 50, canvas.height - xAxisHeight - tickWidth * i + 7); //緩存刻度位置,用於畫網格 stepYArr.push(canvas.height - xAxisHeight - tickWidth * i); } context.stroke(); } /** * 畫網格 * */ var drawGrid = function() { context.save(); context.strokeStyle = "#6e6e6e"; context.fillStyle = "#ffffff"; context.lineWidth = 0.5; //畫橫線 var j = 0,stepX = (canvas.width - 2*yAxisWidth)/10,stepY = (canvas.height - 2*xAxisHeight)/10; //10個像素位為單位,6個像素畫線,4個像素空出來,成為虛線 for (var i = 0,len = stepYArr.length; i < len; i ++) { context.beginPath(); for(j = 0;j < stepX;j++){ context.moveTo(yAxisWidth + j*10, stepYArr[i]); context.lineTo(yAxisWidth + j*10 + 6, stepYArr[i]); } context.stroke(); } //畫豎線 for (var i = 0,len = stepXArr.length; i < len; i ++) { context.beginPath(); for(j = 0;j < stepY;j++){ context.moveTo(stepXArr[i],xAxisHeight + j*10 ); context.lineTo(stepXArr[i],xAxisHeight + j*10+6); } context.stroke(); } context.restore(); } /** * 畫線條 * */ var drawLine = function(lineData){ //循環數據源畫線條 context.beginPath(); context.fillStyle = "#000000"; context.lineWidth = 2; context.moveTo(stepXArr[0] - xStepWidth/2 ,canvas.height - xAxisHeight - lineData[0]*heightVal); for (var i = 1,len = lineData.length; i < len; i ++) { context.lineTo(stepXArr[i] - xStepWidth/2 ,canvas.height - xAxisHeight - lineData[i]*heightVal); } context.stroke(); //畫圓點 for (var i = 0,len = lineData.length; i < len; i ++) { context.beginPath(); context.fillStyle = "rgba(" + (Math.random()*255).toFixed(0) + ", " + (Math.random()*255).toFixed(0) + ", " + (Math.random()*255).toFixed(0) + ", 1.0)"; context.arc(stepXArr[i] - xStepWidth/2 ,canvas.height - xAxisHeight - lineData[i]*heightVal, 7, 0, Math.PI*2, true); context.fill(); } } /** * 畫柱子 * */ var drawBar = function(barData,colorArr){ var barWidth = xStepWidth/2;//定義柱子寬度 //循環數據源畫矩形 for (var i = 0,len = barData.length; i < len; i ++) { context.beginPath(); context.fillStyle = colorArr[i]; context.fillRect(stepXArr[i] - xStepWidth/2 - barWidth/2,canvas.height - xAxisHeight - barData[i]*heightVal, barWidth,barData[i]*heightVal); context.fill(); } } var methods = { init: function(options) { // 在每個元素上執行方法 return this.each(function() { var $this = $(this); // 嘗試去獲取settings,如果不存在,則返回“undefined” var settings = $this.data("lineChart"); // 如果獲取settings失敗,則根據options和default創建它 if (typeof settings === "undefined") { var defaults = { width:850, height:450, xAxis:["蘋果","香蕉","梨","番茄","龍眼"], lineData:[350,200,300,245,150], barData:[350,134,120,51,90], colorArr:["#ae303e","#913730","#D49797","0x538FD3","#A34e5d"], onSomeEvent: function() { } }; settings = $.extend({}, defaults, options); // 保存我們新創建的settings $this.data("lineChart", settings); } else { //如果我們獲取了settings,則將它和options進行合並(這不是必須的,你可以選擇不這樣做) settings = $.extend({}, settings, options); // 如果你想每次都保存options,可以添加下面代碼: // $this.data("lineChart", settings); } canvas = document.createElement("canvas"); canvas.width = settings.width; canvas.height = settings.height; canvas.style.CSSText = "margin:0 auto;"; $this.append(canvas); context = canvas.getContext("2d"); xAxisHeight = settings.height/8 ,yAxisWidth = settings.width/8; drawXAxis(settings.xAxis); drawYAxis(400,10); drawGrid(); drawBar(settings.barData,settings.colorArr); drawLine(settings.lineData); }); }, destroy: function(options) { // 在每個元素中執行代碼 return $(this).each(function() { var $this = $(this); // 執行代碼 // 刪除元素對應的數據 $this.removeData("lineChart"); }); }, val: function(options) { // 這裡的代碼通過.eq(0)來獲取選擇器中的第一個元素的,我們或獲取它的HTML內容作為我們的返回值 var someValue = this.eq(0).Html(); // 返回值 return someValue; } }; $.fn.lineChart = function() { var method = arguments[0]; if (methods[method]) { method = methods[method]; arguments = Array.prototype.slice.call(arguments, 1); } else if (typeof method === "object" !method) { method = methods.init; } else { $.error("Method" + method + "does not exist on jQuery.pluginName"); return this; } return method.apply(this, arguments); }; })(jQuery);