【自己的整理】【jQuery外掛】 使用canvas建立折線圖
使用canvas建立折線圖
一個網友的很常規的需求,要根據資料在一個canvas畫布元素上畫一個折線圖,最開始做了一個很土的版本,現在自己想想還是弄個外掛吧於是就有了這篇文章。
建立jquery外掛標準模板
既然是一個外掛就要按照基本法來,所以先要建立一個標準的jquery外掛模板:
<!DOCTYPE html>
<html>
<head>
<title>用canvas根據資料建立折線圖</title>
<script src="http://code.jquery.com/jquery-latest.js" ></script>
<script>
(function($){
var methods = {
init:function(options){
var chart = $.extend({
'ChartTitle': '三人成績折線圖',//表頭
'defaultLineColor':'rgba(0,0,0,0.4)' ,//折線圖的座標以及輔助線顏色
'defaultTextColor':'rgba(0,0,0,0.7)',//字型顏色
'canvasWidth':800,//畫布寬度
'canvasHeight':600,//畫布高度
'chartWidth':600,//圖示寬度
'chartHeight':400,//圖表高度
'x_metric' :[1,2,3,4,5,6],//月份 下面X軸的計量數
'data':[{
"name":"小紅",
"details":[78,89,86,88,79,88],//資料
"color":"rgba(255,127,127,0.7)"//連線以及點的顏色
},{
"name":"小明",
"details":[86,77,69,76,60,98],
"color":"rgba(127,255,127,0.7)"
},//資料二維陣列
{
"name":"小蘭",
"details":[80,77,66,62,99,65],
"color":"rgba(127,127,255,0.7)"
}],
'startLine':0,//左邊開始的時候的資料
'endLine':120,//左邊最高點的資料
'line_number':4,//中間畫分成幾格子
'x_name':'月份',//縱座標的數量單位
'y_name':'分數'//橫座標的數量單位
},options);
//下面用於檢測是否在已經存在的畫布上畫圖,還是重新生成一個。
var canvasElement,ctx;
if($(this) && $(this).prop("tagName") == "CANVAS"){
var jQueryCanvasObject = $(this);
console.log(jQueryCanvasObject);
canvasElement = jQueryCanvasObject.get(0);
console.log(canvasElement);
ctx = canvasElement.getContext('2d');
canvasElement.width = chart.canvasWidth;
canvasElement.height = chart.canvasHeight;
}else if($(this) && typeof($(this).context) != 'undefined'){
var canvasindex = 0;
for(var canvasindex;$('#drawChartCanvas'+canvasindex+'').length > 0;canvasindex ++ ){
}
$(this).append("<canvas width="+chart.canvasWidth+" height="+chart.canvasHeight+" id='drawChartCanvas"+canvasindex+"'></canvas>");
canvasElement = $("#drawChartCanvas"+canvasindex).get(0);
ctx = canvasElement.getContext('2d');
}
else{
var canvasindex = 0;
for(var canvasindex;$('#drawChartCanvasInBody'+canvasindex+'').length > 0;canvasindex ++ ){
console.log(canvasindex);
}
$('body').append("<canvas width="+chart.canvasWidth+" height="+chart.canvasHeight+" id='drawChartCanvasInBody"+canvasindex+"'></canvas>");
canvasElement = $("#drawChartCanvasInBody"+canvasindex).get(0);
ctx = canvasElement.getContext('2d');
}
},
destory:function(){},//destory方法 待補充
animate:function(){}//其他方法
};
$.fn.drawChart = function (method){
if(methods[method]){
return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
}else if(typeof method === 'object' || !method){
return methods.init.apply(this,arguments);
}else{
$.error('方法'+method+'在畫折線圖外掛中不存在');
}
}
})(jQuery);
</script>
<script>
$(document).ready(function(){$().drawChart()});
</script>
</head>
<body>
</body>
</html>
到目前為止只是建立了一個預設的折線圖資料物件chart,其中包含了諸多資訊,比如表頭,表的線條顏色等,可以根據自己的喜好改變其中某部分的設定。
我們要開始畫一個折線圖的時候,最開始畫的應該是橫豎兩條x軸y軸輔助線,加上代表數量的輔助線,以及單位名稱、度量等。我們在外掛中建立一個新的方法把它叫做drawAxis(),這是一個畫輔助線的方法,並不需要用到資料
function drawAxis(ctx,chart){
ctx.font = "30px microsoft yahei";
ctx.fillStyle = chart.defaultTextColor;
ctx.fillText(chart.ChartTitle,chart.canvasWidth/2-100,40);
ctx.lineWidth = 4;
ctx.strokeStyle = chart.defaultLineColor;
ctx.lineCap = "round";
var bottomLeft = {'x':(chart.canvasWidth - chart.chartWidth)/2,
'y':(chart.canvasHeight - chart.chartHeight)/2+chart.chartHeight
};//左下角點座標
var topRight = {'x':chart.canvasWidth - ((chart.canvasWidth - chart.chartWidth)/2),
'y':(chart.canvasHeight-chart.chartHeight)/2};//右上角點座標
ctx.moveTo((chart.canvasWidth-chart.chartWidth)/2,(chart.canvasHeight-chart.chartHeight)/2+chart.chartHeight);//座標軸原點
ctx.lineTo((chart.canvasWidth-chart.chartWidth)/2,(chart.canvasHeight-chart.chartHeight)/2);//座標軸y軸上部點
var y_metric = chart.chartHeight/chart.line_number;
var between = (chart.endLine - chart.startLine)/(chart.line_number);
for(var i = 0; i < chart.line_number; i++){
ctx.moveTo(bottomLeft.x,bottomLeft.y-i*y_metric);
ctx.lineTo(bottomLeft.x+chart.chartWidth,bottomLeft.y-i*y_metric);
ctx.font = '20px microsoft yahei';
ctx.fillText(Math.floor(between * i + chart.startLine),bottomLeft.x-40,bottomLeft.y-i*y_metric);
};
for(var i = 0;i < chart.x_metric.length; i++){
ctx.moveTo(
i*(chart.chartWidth/chart.x_metric.length)+(chart.canvasWidth-chart.chartWidth)/2+(chart.chartWidth/chart.x_metric.length)/2,
chart.chartHeight + (chart.canvasHeight-chart.chartHeight)/2
);
ctx.lineTo(
i*(chart.chartWidth/chart.x_metric.length)+(chart.canvasWidth-chart.chartWidth)/2+(chart.chartWidth/chart.x_metric.length)/2,
chart.chartHeight + (chart.canvasHeight-chart.chartHeight)/2 + 5
);
ctx.font = "20px microsoft yahei";
ctx.fillText(chart.x_metric[i],
i*(chart.chartWidth/chart.x_metric.length)+(chart.canvasWidth-chart.chartWidth)/2+(chart.chartWidth/chart.x_metric.length)/2 - 6,
chart.chartHeight + (chart.canvasHeight-chart.chartHeight)/2 + 25
);
}
ctx.stroke();
ctx.font = "22px microsoft yahei";
ctx.fillText(chart.x_name,topRight.x + 3,bottomLeft.y);
ctx.fillText(chart.y_name,bottomLeft.x - 3,topRight.y - 10);
for(var i = 0;i < chart.data.length; i++){
ctx.strokeStyle = chart.data[i].color;
ctx.beginPath();
ctx.moveTo(chart.canvasWidth-(chart.canvasWidth-chart.chartWidth)/2, (chart.canvasHeight-chart.chartHeight)/2 +i*25);
ctx.lineTo(chart.canvasWidth-(chart.canvasWidth-chart.chartWidth)/2 + 18, (chart.canvasHeight-chart.chartHeight)/2 +i*25);
ctx.stroke();
ctx.fillText(chart.data[i].name,
chart.canvasWidth-(chart.canvasWidth-chart.chartWidth)/2 + 20,
(chart.canvasHeight-chart.chartHeight)/2 +i*25 +6
);
}
}
然後我們需要在外掛的初始化方法中加入這個方法
init:function(options){
//...省略程式碼
drawAxis(ctx,chart);
}
這樣完成之後我們就可以看到還沒有折線的一個圖示,只有輔助線、表頭、圖例、以及單位等。
在我們在自己的本子上畫折線圖的時候,首先是要畫各個點,然後再把這些點用線連起來,那麼我們就可以按照這個思路來操作。
最開始我們先計算一下點的位置:
function initPointPosition(chart){
var points = [];
for(var g = 0;g < chart.data.length;g++){
var pointsGroup = [];
for(var i = 0;i < chart.data[g].details.length; i++ ){
//獲取資料
var tempNumber = chart.data[g].details[i];
//算出百分比高度位置
var yPercentHeight = ((tempNumber - chart.startLine)/(chart.endLine-chart.startLine))*chart.chartHeight;
//確定位置
var pointPosition = {
'detail':chart.data[g].details[i],
'x':chart.chartWidth/(chart.x_metric.length*2)+i*(chart.chartWidth/chart.x_metric.length)+(chart.canvasWidth-chart.chartWidth)/2,
'y':chart.chartHeight+(chart.canvasHeight-chart.chartHeight)/2-yPercentHeight ,
'color':chart.data[g].color
};
pointsGroup.push(pointPosition);
}
points.push(pointsGroup);
}
return points;
}
這個方法可以根據資料來返回一個二維物件陣列,陣列內的一級元素表示了有多少組點,而二級物件中包含了點的位置,顏色,以及資料等資訊。當然這還只是資料層面的,我們還需要把這些點畫出來,所以需要加入一個可以把這個二維陣列的點畫出來的方法:
function drawPoints(ctx,points){
for(var i = 0; i < points.length; i ++){
for(var j = 0; j < points[i].length; j++){
ctx.fillStyle = points[i][j].color;
ctx.beginPath();
ctx.arc(points[i][j].x,points[i][j].y,4,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}
}
};
我們需要在init(初始化)方法的最後呼叫這個方法:
init:function(options){
//省略的程式碼
drawAxis(ctx,chart);
var points = initPointPosition(chart);
drawPoints(ctx,points);
}
此時我們再重新整理一下瀏覽器,可以看到點已經呈現在折線圖上面了:
這個時候就要把點都連起來,因為之前點的位置已經存在了,所以連點並不難,我們在外掛中加入一個將二維陣列的點連起來的方法:
function drawLine(ctx,points){
ctx.lineWidth = 3.5;
for(var i = 0; i < points.length; i++){
ctx.beginPath();
for(var j = 0; j < points[i].length-1; j++){
ctx.strokeStyle = points[i][j].color;
ctx.moveTo(points[i][j].x,points[i][j].y);
ctx.lineTo(points[i][j+1].x,points[i][j+1].y);
}
ctx.stroke();
}
};
然後同樣在init方法的最後加入:
init:function(options){
drawAxis(ctx,chart);
var points = initPointPosition(chart);
drawPoints(ctx,points);
drawLine(ctx,points);
}
此時我們再重新整理一下瀏覽器,可以看到點之間的連線也連好了。
這個時候可以看到連線已經完成,但是在折線圖中看不到具體的數值,這個大小的比較還是有些看不出來,所以我們還要在點的旁邊畫上資料,同樣新建一個方法用來繪製具體數值:
function drawData(ctx,points,chart){
ctx.fillStyle = chart.defaultTextColor;
ctx.font = "18px microsoft yahei";
for(var i = 0;i < points.length; i++){
for(var j = 0;j< points[i].length;j++){
ctx.fillText(points[i][j].detail,points[i][j].x,points[i][j].y);
}
}
}
同理要在init方法最後加入繪製具體數值的方法:
init:function(options){
//省略的內容
drawAxis(ctx,chart);
var points = initPointPosition(chart);
drawPoints(ctx,points);
drawData(ctx,points,chart);
}
最後再次重新整理一下瀏覽器,可以看到一個較為完整的折線圖:
看起來有些緊湊,想要把它變得不那麼緊湊的話,可以改變一些設定:
<script>
$().drawChart({"startLine":50,"endLine":100});
</script>
測試地址
相關推薦
【自己的整理】【jQuery外掛】 使用canvas建立折線圖
使用canvas建立折線圖 一個網友的很常規的需求,要根據資料在一個canvas畫布元素上畫一個折線圖,最開始做了一個很土的版本,現在自己想想還是弄個外掛吧於是就有了這篇文章。 建立jquery外掛標準模板 既然是一個外掛就要按照基本法來,所以先要建立
spring method validation的優化【自己動手實現校驗切面】
建議首先閱讀筆者的Spring method validation的不足 在【Spring method validation的不足】的文章中,筆者提出瞭如下問題: spring method validation 不支援方法物件檢視的校驗; 方法級別的校驗規則是統
jQuery外掛之【jqGrid】常用語法整理-【更新】
jqGrid常用語法整理,包含資料獲取、常用函式、觸發事件等 jqGrid表格資料獲取相關語法 獲取表格所有資料 $("#grid").jqGrid("getRowData"); 根據行id獲取表
【jQuery Demo】圖片切換效果整理
ges 比較 nta containe 水平滾動 :hover 實現 small vertica 圖片的切換效果有很多,比較常見的有水平滾動、垂直滾動、淡入淡出等。我們接下來一一實現這些效果。 1.水平滾動 1) 我們先來實現HTML頁面,代碼很簡單: &l
【總結整理】overflow: auto/hidden;清除自己
12px borde 清除浮動 nav pre flow 需要 效果 size .top-nav{ font-size: 12px; font-weight: bold; li
【總結整理】JQuery基礎學習---事件篇
交互 .... over 指針 events 返回值 避免 func 坐標 jQuery鼠標事件之click與dbclick事件 用交互操作中,最簡單直接的操作就是點擊操作。jQuery提供了兩個方法一個是click方法用於監聽用戶單擊操作,另一個方法是dbclick方
【jQuery外掛分享】Cropper——一個簡單方便的圖片裁剪外掛
原文地址:https://segmentfault.com/a/1190000012344970 外掛介紹 這是一個我在寫以前的專案的途中發現的一個國人寫的jQuery影象裁剪外掛,當時想實現使用者資料的頭像上傳功能,並且能夠預覽圖片,和對圖片進行簡單的裁剪、旋轉,花了不少
【常用 JS 外掛】01 jQuery Validation 表單驗證外掛
表單驗證框架 jQuery Validation 前端表單驗證框架 頁面引用 <!-- jQuery Validation 1.14.0 --> <script src="/static/assets/plugins/jquery-valida
【常用 JS 外掛】01 jQuery Valdation 表單驗證外掛
表單驗證框架 jQuery Validation 前端表單驗證框架 頁面引用 <!-- jQuery Validation 1.14.0 --> <script src="/static/assets/plugins/jquery-valida
【常用 JS 外掛】jQuery zTree 樹形結構外掛
zTree zTree 是一個依靠 jQuery 實現的多功能 “樹外掛”。優異的效能、靈活的配置、多種功能的組合是 zTree 最大優點。 頁面引用 CSS 部分 <link rel="stylesheet" href="/static/assets/
【外掛】自適應佈局JQuery外掛,rem佈局——和派孔明
//框架檔名Pandora.AutoSize.js (function($) { $.fn.extend({ AutoSize: function() {
【jQuery】圖片燈箱外掛——lightBox
該外掛可以用圓角的方式展示選擇中的圖片,使用按鈕檢視上下張圖片,在載入圖片時自帶進度條,還能以自動播放的方式瀏覽圖片,呼叫格式如下: $(linkimage).lightBox({options}) 其中linkimage引數為包含圖片的<a>元素名稱,o
【原】react中如何使用jquery外掛
react的思想是虛擬dom,提倡最好較少dom的操作,可是我們在寫網頁的時候,有些複雜的互動還是離不開jquery外掛的。而且當你把jquery直接拿來用的時候,你會發覺會報錯,要麼是找不到那個外掛,要麼就是沒有報錯,但是就是不能用。尤其是使用webpack打包後,如果將外掛一起打包,那可能會出錯。
【常用 JS 外掛】jQuery DataTables 自定義查詢
前提 因為需要根據不同的分類查詢資料,可以點選一個按鈕,重新重新整理表格。 js "ajax": { "url": "/article/page", "data":function (d) { d.cid = $("#cid"
【常用 JS 外掛】jQuery TreeTable 樹表格外掛
TreeTable treeTable 是跨瀏覽器、效能很高的 jQuery 的樹表元件,它使用非常簡單,只需要引用 jQuery 庫和一個 js 檔案,介面也很簡單。 優點: 相容主流瀏覽器:支援 IE6 和 IE6+, Firefox, chrome, Opera,
jQuery Handsontable【jQuery外掛-一個非常酷的可編輯表格】
jQuery Handsontable 是jQuery外掛中一款非常酷的可編輯的表格,它的描述是:a minimalistic Excel-like data grid editor for HTML, JavaScript & jQuery. (一款類似於Exce
【jquery-jqGrid外掛】jqGrid 多選 複選框 編輯列
jqGrid 表格外掛- 表格多選複選框,編輯列使用 1、當在JqGrid表格屬性中設定了multiselect:true,這時會在每一行前面出現checkbox。 2、而在點選欄的ch
【JQuery UI】微調按鈕外掛——spinner
微調按鈕外掛不僅能在文字框中直接輸入數值,還可以通過點選輸入框右側的上下按鈕修改輸入框的值,還支援鍵盤的上下方向鍵改變輸入值,呼叫格式如下: $(selector).spinner({options}
【自己的整理】Vue入門使用
為什麼要用vue 寫這篇部落格的時間,2018年4月20日。我們為什麼要用vue 前端框架層出不窮的今天,選擇一個較為主流同時能讓自己事半功倍的框架是必不可少的,同時vue作為三大主流框架之一發展迅速,如果還沒有選擇好用哪個框架,那不如稍微考慮一下,只要選定
【自己的整理】node.js建立靜態路由以及Router建立路由
node.js路由的設定 靜態路由 首先作為基礎的建立一個靜態路由,是在express中最簡單的路由建立方法,這樣就可以訪問靜態路由下的任何一個存在的檔案。 先要建立一個js檔案,檔案命名隨便,比如我就把它叫做static.js,然後我們需要檢視路由是