您的位置:首页 > Web前端 > JavaScript

简单使用canvas 绘制总量图,饼图,折线图2

2017-09-18 15:17 316 查看
拷贝下去跑一跑,
后端返回的数据格式都很简单,
看下面的demo,改改就可以了。
<html><head lang="en"></head><body><table><tr><td> <canvas id="rectangle" width="250" height="250" style="display: none"></canvas> </td><td> <canvas id="rectangle1" width="250" height="250" style="display: none"></canvas> </td><td> <canvas id="rectangle2" width="250" height="250" style="display: none"></canvas> </td><td> <canvas id="rectangle3" width="250" height="250" style="display: none"></canvas> </td></tr></table><br /><canvas id="bar"  width="1324" height="250" style="display: none"> </canvas><br /><canvas id="line" width="1324" height="250" style="display: none"></canvas><br /><br /><br /><canvas id="line1" width="1324" height="250" style="display: none"></canvas><br /><canvas id="curve" width="1324" height="250" style="display: none"></canvas><script>var metric_values = {{ metric_values }};var flag = '{{ flag }}';window.onload = function(){if(flag == '课内_口语评测_总览页面'){{# 画出每天提交的口语评测的量 #}drawBar({id:'bar',label: metric_values[1]['value']['date_list'],//x轴的标题values: metric_values[1]['value']['value_list'], //对应标签的值fillColor: "black", //矩形填充颜色xtitle: "口语评测日提交量", //x轴标题ytitle: "日期" //y轴标题});{# 画出口语评测总量 #}drawRectangle({id:'rectangle',color:  "lightgreen", //颜色text: ["口语评测提交总量 : ", metric_values[0]['value'][0]['value']] //标签})}else if(flag == '课内_闯关游戏_总览页面'){drawRectangle({id:'rectangle',color:  "lightgreen", //颜色text: ["游戏总闯关量 : ",metric_values[0]['value'][0]['value']] //标签});drawRectangle({id:'rectangle1',color:  "lightgreen", //颜色text: ["游戏总PK量 : ",metric_values[0]['value'][1]['value']] //标签});drawRectangle({id:'rectangle2',color:  "lightgreen", //颜色text: ["班级圈内总闯关量 : ",metric_values[0]['value'][2]['value']] //标签});drawRectangle({id:'rectangle3',color:  "lightgreen", //颜色text: ["班级圈内总PK量 : ",metric_values[0]['value'][3]['value']] //标签});drawLine({id:'line',labels: metric_values[1]['value']['date_list'],//标签values1: metric_values[1]['value']['value_list'],//值values2: metric_values[2]['value']['value_list'],//值lineColor1:"blue",//折线颜色lineColor2:"red",//折线颜色circleColor1:"blue",//折线上原点颜色circleColor2:"red",//折线上原点颜色title:'闯关总量、班级圈闯关总量折线图(蓝色:闯关总量; 红色:班级圈闯关总量)'});drawLine({id:'line1',labels: metric_values[1]['value']['date_list'],//标签values1: metric_values[3]['value']['value_list'],//值values2: metric_values[4]['value']['value_list'],//值lineColor1:"blue",//折线颜色lineColor2:"red",//折线颜色circleColor1:"blue",//折线上原点颜色circleColor2:"red",//折线上原点颜色title:'PK总量、班级圈PK总量折线图(蓝色:PK总量; 红色:班级圈PK总量)'});}else if(flag == '平台_班级圈_总览页面'){{# 画出口语评测总量 #}drawRectangle({id:'rectangle',color:  "lightgreen", //颜色text: ["班级圈总量 : ",metric_values[0]['value'][0]['value']] //标签});{# 画出口语评测总量 #}drawRectangle({id:'rectangle1',color:  "lightgreen", //颜色text: ["班级圈用户总量 : ",metric_values[0]['value'][1]['value']] //标签});{# 画出每天提交的口语评测的量 #}drawBar({id:'bar',label: metric_values[1]['value']['date_list'],//x轴的标题values: metric_values[1]['value']['value_list'], //对应标签的值fillColor: "black", //矩形填充颜色xtitle: "过去30天每天加入班级圈人数", //x轴标题ytitle: "日期" //y轴标题});}};{# 画矩形 #}function drawRectangle(args) {var c = document.getElementById(args.id);c.style.display="block";var ctx = c.getContext("2d");ctx.fillStyle= args.color ;ctx.fillRect(0,0,200,200);ctx.font = "20px Georgia";ctx.fillStyle="black";for(var index=0; index< args.text.length; index++){var text = args.text[index];ctx.fillText(text, 10, 30+index*25);}{#        ctx.font = "30px Verdana";#}// 创建渐变{#        var gradient = ctx.createLinearGradient(0, 0, c.width, 0);#}{#        gradient.addColorStop("0", "magenta");#}{#        gradient.addColorStop("0.5", "blue");#}{#        gradient.addColorStop("1.0", "red");#}// 用渐变填色{#        ctx.fillStyle = gradient;#}{#        ctx.fillText("w3school.com.cn", 10, 90);#}}{# 柱状图 #}function drawBar(args){var bar = document.getElementById(args.id);bar.style.display="block";data = {label: args.label,//x轴的标题dataSets: [{bDistance: 30, //绘制的边框距离画布边框的距离bInterval: 20, //两个柱状图之间的距离values: args.values, //对应标签的值fillColor: "rgba(0,0,255,0.5)" //矩形填充颜色},{txtfont: "9px microsoft yahei",//绘制文本的字体txtalgin: "center",//文本对齐方式txtbaseline: "middle"//文本的基线},{fillColor: args.fillColor, //矩形填充颜色xtitle: args.xtitle, //x轴标题ytitle: args.ytitle //y轴标题}]};barChart(bar, data); //画柱状图}function drawPie(args){var pie = document.getElementById(args.id);pie.style.display="block";datasets = {colors: args.colors, //颜色 列表labels: args.labels, //标签 列表values: [100], //值 列表x: 125, //圆心x坐标y: 125, //圆心y坐标radius: 100 //半径};pieChart(pie, datasets); //画饼状图}function drawLine(args){//画折线图var line = document.getElementById(args.id);line.style.display="block";var  datas = {labels: args.labels,//标签values: args.values1,//值txtSet: {//绘制文本设置txtfont: "10px microsoft yahei",txtalgin: "center",txtbaseline: "middle",txtColor:"#000000"},bgSet:{//绘制背景线设置lineColor:"#C0C0C0",lineWidth:1},lineColor:args.lineColor1,//折线颜色circleColor:args.circleColor1,//折线上原点颜色yAxis:{//y轴表示什么,及绘制文本的位置x:205,y:11,title:args.title}};var  newData = {labels: args.labels,//标签values: args.values2,//值txtSet: {txtfont: "10px microsoft yahei",txtalgin: "center",txtbaseline: "middle",txtColor:"#000000"},bgSet:{lineColor:"#C0C0C0",lineWidth: 1},lineColor:args.lineColor2,circleColor:args.circleColor2,yAxis:{x:205,y:11,title:args.title}};var max_height = Math.max.apply(null, [Math.max.apply(null, datas.values) , Math.max.apply(null, newData.values) ]);datas['max_height'] = max_height;newData['max_height'] = max_height ;lineChart(line, datas);//画折线图lineChart(line, newData);//在同一个canvas画第二条折线图//curveChart();//绘制曲线}function drawCurve(){var bg = document.getElementById("curve")linedata = {labels: ["1月", "2月", "3月", "4月", "5月", "6月", "7月"],//标签datas: [115, 35, 210, 100, 300, 220, 40],//数据xTitle: "月份",//x轴标题yTitle: "产量(个)",//y轴标题ctxSets:{strokeColor:"#C0C0C0",//背景线颜色lineWidth:1,//线的宽度txtColor:"#000000",//绘制文本颜色txtFont:"12px microsoft yahei",//字体txtAlign:"center",//对齐方式txtBase:"middle",//基线lineColor:"blue",//折线颜色circleColor:"#FF0000"//折线上圆点颜色}};setBg(bg,linedata);//绘制图标背景及折线}//数组sort()排序传的参数为该函数(降序排列),绘制柱状图需要function compare(value1, value2) {return value2 - value1;}/*柱状图* elem:要操作的画布元素* data:所需格式的数据*/function barChart(elem, data) {if (elem.getContext) {var ctx = elem.getContext("2d"),mywidth = elem.width, //画布的宽高myheight = elem.height,bDistance = parseInt(data.dataSets[0].bDistance), //图标边框到画布间距bInterval = data.dataSets[0].bInterval, //矩形间间距labels = data.label, //矩形对应标题len = labels.length,//标签/数据个数//矩形宽度bWidth = Math.floor((mywidth - bDistance * 2 - (len + 1) * bInterval) / len),bheight = myheight - bDistance * 2, //边框高度values = data.dataSets[0].values, //绘图的值sortValues = values.slice(0), //基于当前数组中的一个或多个项创建一个新数组(解决了该数组排序原数组也被排序的问题)serialValues = new Array(); //用于存储序列化后的值sortValues.sort(compare);if (sortValues[0] > bheight) {(function() {//数值超过边框高度时序列化值for (var i = 0; i < len; i++) {serialValues[i] = values[i] * bheight / sortValues[0];}})(); //块级作用域}//绘制边框ctx.beginPath(); //要绘制路径,必须先调用该方法,表示开始绘制新路径ctx.moveTo(bDistance, bDistance);ctx.lineTo(bDistance, myheight - bDistance);ctx.lineTo(mywidth - bDistance, myheight - bDistance);ctx.stroke(); //把图形绘制到画布上//绘制矩形,组成条形图ctx.fillStyle = data.dataSets[0].fillColor;//绘制文字ctx.font = data.dataSets[1].txtfont; //字体样式、大小、字体ctx.textAlign = data.dataSets[1].txtalgin; //文本对齐方式ctx.textBaseline = data.dataSets[1].txtbaseline; //文本的基线for (var i = 0; i < len; i++) {var x = (bInterval + bDistance) + i * (bWidth + bInterval),y = myheight - serialValues[i] - bDistance,x1 = x + Math.round(bWidth / 2);y1 = myheight - bDistance + 15,y2 = y - 10;ctx.fillRect(x, y, bWidth, serialValues[i]); //x,y,width,height单位都为pxctx.fillText(labels[i], x1, y1); //绘制标题文字ctx.fillText(values[i], x1, y2); //绘制柱状图数据}ctx.fillStyle = data.dataSets[2].fillColor;ctx.fillText(data.dataSets[2].xtitle, 100, 7); //x轴代表什么ctx.fillText(data.dataSets[2].ytitle, mywidth - bDistance, myheight - bDistance + 15); //y轴代表什么}}//求和,计算百分比(画饼图时需要)function sumFunc(data) {var sum = 0;for (var i = 0, len = data.length; i < len; i++) {sum += data[i];}return sum;}/*饼图* elem:要操作的画布元素* data:所需格式的数据*/function pieChart(elem, data) {if (elem.getContext) {var ctx = elem.getContext("2d"),vdata = data.values, //绘图数据sum = sumFunc(vdata), //对绘图数据求和,用于计算百分比startangle = 0, //绘制扇形的开始角度labels = data.labels, //绘图的对应文字x = data.x, //圆心x坐标y = data.y, //圆心y坐标rad = data.radius, //圆半径x1 = x + rad + 30, //绘制右侧文字和标注的x坐标y1 = y - rad, //绘制右侧文字和标注的y坐标endangle; //绘制扇形的结束角度for (var i = 0, len = vdata.length; i < len; i++) {//绘制饼图//计算下一次绘制扇形的结束角度,即根据绘制数据占有总数据和的比例求的弧度var percent = vdata[i] / sum;endangle = startangle + Math.PI * 2 * (percent);ctx.beginPath(); //开始绘制新路径ctx.fillStyle = data.colors[i]; //绘制颜色ctx.moveTo(x, y); //移动到圆心(注:画饼图一定要回到圆心,不然会有问题)ctx.arc(x, y, rad, startangle, endangle, false); //画扇形//绘制右侧文字和标注ctx.moveTo(x1, y1); //移动到绘制文字和标注的位置{#         ctx.fillRect(x1, y1, 30, 14); //绘制矩形表示比列图#}//计算四舍五入后的扇形每份的百分比var perc = (percent * 100).toFixed(2) + "%"; //tofixed()自动四舍五入返回指定小数位数的字符串//设置绘制文字的属性ctx.font = "bold 12px microsoft yahei";ctx.txtalgin = "center";ctx.textBaseline = "top";//绘制文字ctx.fillText(labels[i], x1 , y1);{#       ctx.fillText(labels[i] + ":" + perc, x1 + 35, y1);#}ctx.fill(); //指定颜色填充以上绘制startangle = endangle; //下一次绘制扇形的开始角度y1 += 20; //下一次绘制文字和标注的y坐标}}}/*绘制折线elem:操作的元素data:所需格式数据*/function lineChart(elem, data) {if (elem.getContext) {var labels = data.labels,//数值对应标签values = data.values,//数值len = labels.length,//标签/数值个数elemWidth = elem.width,//画布宽度elemHeight = elem.height,//画布高度gridHeight = Math.ceil(elemHeight / 5),//每行之间高度gridWidth = Math.floor(elemWidth / len),//每列之间看度actualHeight = 4 * gridHeight + 20;//绘制区域实际高度var ctx = elem.getContext("2d");//设置绘制直线的属性ctx.strokeStyle = data.bgSet.lineColor;ctx.lineWidth = data.bgSet.lineWidth;//设置绘制文本的属性ctx.font = data.txtSet.txtfont;ctx.textAlign = data.txtSet.txtalgin;ctx.txtbaseline = data.txtSet.txtbaseline;//绘制背景//绘制背景横线ctx.beginPath();for (var i = 0; i < 5; i++) {var hgridY = gridHeight * i + 20,hgridX = gridWidth * len;ctx.moveTo(0, hgridY);ctx.lineTo(hgridX, hgridY);}ctx.stroke();//绘制背景的竖线,表示每个labelctx.beginPath();for (var j = 0; j < len + 1; j++) {var vgridX = gridWidth * j,vgridY = actualHeight;ctx.moveTo(vgridX, vgridY);ctx.lineTo(vgridX, vgridY + 10);}ctx.stroke();//绘制标签文字ctx.fillStyle = data.txtSet.txtColor;for (var k = 0; k < len; k++) {var txtX = gridWidth * (k + 0.5),txtY = actualHeight + 15;ctx.fillText(labels[k], txtX, txtY);}ctx.fill();//获取画图数据的最大值用于序列换数据var maxValue = data.max_height,cData = new Array();//当最大值大于画布可绘制区域的高度时,对数据进行转化,然后进行画图if ((4 * gridHeight) < maxValue) {var rate = 4 * gridHeight / maxValue;for (i = 0; i < len; i++) {//转换后的数据cData[i] = Math.round(values[i] * rate)}} else {cData = values;}//绘制折线ctx.strokeStyle = data.lineColor;ctx.beginPath();var pointX = gridWidth / 2,pointY = actualHeight - cData[0];ctx.moveTo(pointX, pointY);for (i = 1; i < len; i++) {pointX += gridWidth;pointY = actualHeight - cData[i];ctx.lineTo(pointX, pointY);}ctx.stroke();//绘制坐标圆形ctx.beginPath();ctx.fillStyle = data.circleColor; //圆点的颜色for (var i = 0; i < len; i++) {var circleX = gridWidth / 2 + gridWidth * i,circleY = actualHeight - cData[i];ctx.moveTo(circleX, circleY); //假如不每次绘制之前确定开始绘制新路径,可以每次绘制之前移动到新的圆心ctx.arc(circleX, circleY, 4, 0, Math.PI * 2, false);}ctx.fill();//绘制坐标圆形对应的值ctx.beginPath();ctx.fillStyle = data.txtSet.txtColor;; //文本颜色for (var i = 0; i < len; i++) {var circleX = gridWidth / 2 + gridWidth * i,circleY = actualHeight - cData[i];ctx.fillText(values[i], circleX, circleY - 8);}ctx.fill();//绘制y轴代表什么ctx.fillText(data.yAxis.title, data.yAxis.x, data.yAxis.y);ctx.fill();}}function curveChart() {var elem = document.getElementById("curve");if (elem.getContext) {var ctx = elem.getContext("2d");//       ctx.lineWidth = 2;ctx.lineCap = "square";ctx.beginPath();ctx.moveTo(100, 70);ctx.bezierCurveTo(120, 150, 150, 150, 200, 60); //三次贝赛尔曲线ctx.moveTo(40, 100);ctx.quadraticCurveTo(60, 60, 100, 70); //二次贝塞尔曲线ctx.moveTo(200, 60);ctx.arcTo(240, 40, 300, 50, 50); //绘制弧线ctx.stroke();}}/* 绘制背景* elem:要操作的元素* data:所需格式的数据*/function setBg(elem, data) {if (elem.getContext) {var ctx = elem.getContext("2d"),//获取元素上下文startX = 40,//左上角开始绘制的x坐标startY = 40,//左上角开始绘制的y坐标labels = data.labels,//对应数据的标签,即列数cols = labels.length,//数据个数datas = data.datas,//数据gWidth = elem.width - 80,//背景总宽度,elem.width为画布宽度gHeight = elem.height - 80,//背景总长度pgWidth = gWidth / cols,//背景每个格的宽度rows = 10,//背景表格行数pgHeight = gHeight / rows;//背景表格高度//绘制背景ctx.beginPath(); //开始绘制新路径ctx.strokeStyle = data.ctxSets.strokeColor;//描边颜色ctx.lineWidth = data.ctxSets.lineWidth;//描边线条宽度//绘制横线for (var i = 0; i < rows; i++) {var pY = startX + pgHeight * i;ctx.moveTo(startX, pY); //移动到绘制的起点ctx.lineTo(gWidth + startX, pY);}//最后一根横线var pY1 = startY + pgHeight * rows;ctx.moveTo(startX, pY1); //移动到绘制的起点ctx.lineTo(gWidth + startX + 20, pY1);//绘制竖线//第一根竖线ctx.moveTo(startX, startY - 20); //移动到绘制的起点ctx.lineTo(startX, gHeight + startY + 10);for (var i = 1; i < cols + 1; i++) {var pX = startX + pgWidth * i;ctx.moveTo(pX, startY); //移动到绘制的起点ctx.lineTo(pX, gHeight + startY + 10);}ctx.stroke();//把图形绘制到画布上//绘制文字ctx.fillStyle = data.ctxSets.txtColor;//填充颜色ctx.font = data.ctxSets.txtFont;//文本字体ctx.textAlign = data.ctxSets.txtAlign;//文本对齐方式ctx.textBaseline = data.ctxSets.txtBase;//文本基线//绘制横轴文字for (var i = 0; i < cols; i++) {var px = startX + pgWidth / 2 + pgWidth * i;ctx.fillText(labels[i], px, startY + gHeight + 10);}//绘制竖轴文字//判断最大值是否大于行高,确定每行的数值var maxValue = 0,newValues = new Array(),j = 0;for (var i = 0; i < cols; i++) {if (datas[i] > maxValue) {maxValue = datas[i];}}//重新计算每隔数据值及转换值if (maxValue > gHeight) {pgValues = maxValue / rows;for (var i = 0; i < cols; i++) {newValues[i] = datas[i] * gHeight / maxValue;}} else {pgValues = pgHeight;newValues = datas;}//绘制竖轴文字for (var i = rows; i >= 0; i--) {ctx.fillText(pgValues * i, 20, startY + pgHeight * j);j++;}//绘制标题//x轴标题ctx.fillText(data.xTitle, gWidth + startX + 15, gHeight + startY + 10);//y轴标题ctx.fillText(data.yTitle, startX + 25, startY - 10);//画图//绘制折线ctx.strokeStyle = data.ctxSets.lineColor;;ctx.beginPath();var pointX = pgWidth / 2 + startX,pointY = startY + gHeight - newValues[0];ctx.moveTo(pointX, pointY);for (var i = 1; i < cols; i++) {pointX += pgWidth;pointY = startY + gHeight - newValues[i];ctx.lineTo(pointX, pointY);}ctx.stroke();//绘制坐标圆形ctx.beginPath();ctx.fillStyle = data.ctxSets.circleColor;; //圆点的颜色for (var i = 0; i < cols; i++) {var circleX = pgWidth / 2 + startX + pgWidth * i,circleY = startY + gHeight - newValues[i];ctx.moveTo(circleX, circleY); //假如不每次绘制之前确定开始绘制新路径,可以每次绘制之前移动到新的圆心ctx.arc(circleX, circleY, 4, 0, Math.PI * 2, false);}ctx.fill();//绘制坐标圆形对应的值ctx.beginPath();ctx.fillStyle = data.ctxSets.txtColor; //文本颜色for (var i = 0; i < cols; i++) {var circleX = pgWidth / 2 + startX + pgWidth * i,circleY = startY + gHeight - newValues[i];ctx.fillText(datas[i], circleX, circleY - 10);}ctx.fill();}}</script></body></html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息