原文:https://code.tutsplus.com/zh-...
原做:John Negoita
翻译:Stypstive javascript
在这篇教程中,我将展现用JavaScript和canvas做为手段,在饼状图和圆环图上显示数字信息。html
与从零到一建立图表相比,其实有更简便的方式,例如用CodeCanyon上的这个图表库html5
可是若是你想知道库背后的原理,往下读。java
图表是用来图形化展现数据的工具。 饼状图将数据用切割成份的圆来展现。 每份的大小表明了数据值所表明的比例大小。canvas
简而言之,圆环图是饼状图的一个变种。 不一样的是每份切向饼图的中心,这样只有轮缘是可见。 就这样,图表就如其名一个圆环。数组
绘制饼图以前, 咱们先看看它的组成部分。 咱们先看看如何用canvas组件和JavaScript来画:网络
一条线ide
一个弧度(一个圆的部分)wordpress
一个颜色填充的图形函数
要想用HTML canvas画它,咱们须要先建立几样东西:
建立一个项目文件夹,把它命名为piechart-tutorial
在piechart-tutorial
文件夹中建立一个HTML文件index.html
这个文件中将是HTML代码。
一个JS文件scritp.js
在piechart-tutorial
文件夹中 这个文件中将是JavaScript代码。
咱们将能简就简,而后添加一下代码到index.html
中:
<html> <body> <canvas id="myCanvas"></canvas> <script type="text/javascript" src="script.js"></script> </body> </html>
咱们有一个ID为myCanvas
的<canvas>
元素。 而后咱们经过<script>
标签载入JS代码。
在script.js
中,JS代码首先获取一个canvas的索引,而后设置canvas的宽和高。 要想在canvas上画,咱们只须要一个2D上下文,哪里包含着全部的绘图方法。
var myCanvas = document.getElementById("myCanvas"); myCanvas.width = 300; myCanvas.height = 300; var ctx = myCanvas.getContext("2d");
如今咱们已经设置了canvas的宽和高,同时也获取了canvas的索引,接下来咱们定义一些画饼状图时,须要用到的可重用的函数。 咱们将函数添加在script.js文件中。
function drawLine(ctx, startX, startY, endX, endY){ ctx.beginPath(); ctx.moveTo(startX,startY); ctx.lineTo(endX,endY); ctx.stroke(); }
函数drawLine
接受5个参数:
ctx
: 指向绘图上下文的索引
startX
:线段起始点的X坐标
startY
:线段起始点的Y坐标
endX
:线段结束点的X坐标
endY
:线段结束点的Y坐标
咱们经过调用beginPath()
来开始划线。 它通知绘图上下文,咱们要在canvas上画一些东西了。 咱们用moveTo()
来设置起始点,调用lineTo()
来表示结束点,而后调用stoke()
来进行真正的绘图。
如今看看咱们如何画圆的一部分,也叫作弧度。
function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle){ ctx.beginPath(); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.stroke(); }
函数drawArc
接受6个参数:
ctx
:指向绘图上下文的索引
centerX
:圆心的X坐标
centerY
:圆心的Y坐标
radius
: 圆的半径
startAngle
:部分圆的扇形的开始角度
endAngle
: 部分圆的扇形的结束角度
咱们已经知道怎样画线和弧度了,如今让我看看如何画带颜色的形状。 因为咱们的目标是画一份份组成的饼状图,因此咱们建立一个画饼形图的份的函数。
function drawPieSlice(ctx,centerX, centerY, radius, startAngle, endAngle, color ){ ctx.fillStyle = color; ctx.beginPath(); ctx.moveTo(centerX,centerY); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.closePath(); ctx.fill(); }
函数drawPieSlice
接受7个参数:
ctx
:指向绘图上下文的索引
centerX
:圆心的X坐标
centerY
:圆心的Y坐标
radius
:圆的半径
startAngle
:部分圆的扇形的起始角度
endAngle
:部分圆的扇形的结束角度
color
:填充的颜色
如下是调用这三个函数的例子:
drawLine(_ctx,100,100,200,200); drawArc(_ctx, 150,150,150, 0, Math.PI/3); drawPieSlice(_ctx, 150,150,150, Math.PI/2, Math.PI/2 + Math.PI/4, '#ff0000');
它将产生以下结果:
如今,咱们有了画一个饼形图的全部必要的工具,让咱们看看如何一块儿使用它们。
在概念上,任意图表都有两部分:
包含要展现的数据的数据模型。 这由特定类型的图表进行结构化。
图形化展现是指按照数学公式的规则,将数据模型中的数据经过视觉元素来进行展现。
饼状图数据模型
结构化饼状图数据的方式中,最经常使用的就是用一系列的类别和对应的值,每一个类别的值与饼图的份相关联。
例如,饼图的数据模型展现按照流派进行分组,看起来就是下面这样:
古典音乐:10
另类摇滚:14
流行:2
爵士:12
咱们能够在script.js文件中添加一个JS对象来存储数据模型,以下:
var myVinyls = { "Classical music": 10, "Alternative rock": 14, "Pop": 2, "Jazz": 12 };
饼状图的图形化展现
饼状图用圆来显示数据模型中的信息,经过将圆切分红一份份。 每份和数据模型中的类别对应,每份的大小与对应类别的值成正比。
个人音乐集有四个类别。 每一个类别在饼形图中的份数大小,与它的类别对应的值成正比。
可是咱们怎样度量份数的大小? 简单--咱们经过每份的角度。 咱们所须要知道的就是它占360度或者2PI的份数。 那么半圆就是180deg或者PI,1/4圆90度或PI/2,以此类推。
为了决定每一个类别的份的角度,咱们用如下公式:
份角度= 2 * PI * 类别值 / 总值
按照这个公式,古典音乐的那份近似获得以下角度。 0.526 * PI 或者 94度
让我开始画吧。 此次咱们将用JavaScript类,将其命名为 PieChart
构造函数接受options作为参数,options包含如下:
canvas:指向咱们想要画饼状图的索引
data:盛放数据模型的对象的索引
colors:一个数组,数组中是每份的颜色。
PieChart
类同时也包含一个draw()
方法,它来对图表进行实际的绘制。
var Piechart = function(options){ this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.draw = function(){ var total_value = 0; var color_index = 0; for (var categ in this.options.data){ var val = this.options.data[categ]; total_value += val; } var start_angle = 0; for (categ in this.options.data){ val = this.options.data[categ]; var slice_angle = 2 * Math.PI * val / total_value; drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, Math.min(this.canvas.width/2,this.canvas.height/2), start_angle, start_angle+slice_angle, this.colors[color_index%this.colors.length] ); start_angle += slice_angle; color_index++; } } }
类中首先将传入的options
参数进行存储。 它保存了canvas
的索引,同时也建立一个绘画上下文做为类成员变量。 而后它存储了options中的colors
数组。
接下来的部分是最根本的,函数draw()
。 它会从数据模型中提取数据。 首先,它计算数据模型中全部数据值的和。 而后对其中每一个类别应用上面提到的计算角度的函数。 最后咱们调用drawPieSlice()
函数,用canvas的中心做为饼状图的中心。 至于半径,咱们用canvas宽度的一半与canvas高度的一半的较小值,由于咱们不想让饼状图超出canvas。
一样,每次画一个类别时,要偏移每份的起始角度和结束角度,不然会发生重叠。
要想使用类,咱们必须先建立一个实例对象,而后在建立的对象上调用draw()
方法。
var myPiechart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"] } ); myPiechart.draw();
结果看起来以下这样:
咱们已经看到如何建立饼状图。 一样咱们看到,圆环图与饼状图不一样之处仅在于中间多了一个洞。 怎样画洞呢? 咱们能够画一个白色的圆在饼状图上。
让咱们经过修改PieChart
类来作它。
var Piechart = function(options){ this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.draw = function(){ var total_value = 0; var color_index = 0; for (var categ in this.options.data){ var val = this.options.data[categ]; total_value += val; } var start_angle = 0; for (categ in this.options.data){ val = this.options.data[categ]; var slice_angle = 2 * Math.PI * val / total_value; drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, Math.min(this.canvas.width/2,this.canvas.height/2), start_angle, start_angle+slice_angle, this.colors[color_index%this.colors.length] ); start_angle += slice_angle; color_index++; } //drawing a white circle over the chart //to create the doughnut chart if (this.options.doughnutHoleSize){ drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, this.options.doughnutHoleSize * Math.min(this.canvas.width/2,this.canvas.height/2), 0, 2 * Math.PI, "#ff0000" ); } } }
添加的代码在options
参数中,经过一个doughnutHoleSize
成员变量。 若是这个参数在options中没有传,代码就按照以前的进行绘制,若是传了,就在饼状图中心画一个白色的圆形。
圆的半径由饼形图的半径和doughnutHoleSize
参数的乘积来决定。 它应该是0到1之间的数字,0表明饼形图,大于0时,值越大饼形图中间的洞越大,当值为1时会使图表不可见。
要想画一个图表一半大小的圆环图,咱们能够将doughnutHoleSize
设置为0.5,而后像下面这样调用:
var myDougnutChart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"], doughnutHoleSize:0.5 } ); myDougnutChart.draw();
如下是结果:
咱们的饼状图表和圆环图表看起来挺棒了,可是它会变得更棒,经过添加两样东西:
值标签:显示每份对应的百分比
图表图例:显示图表中每一个类别和颜色的对应关系
一般,每份的值用百分比来表示,经过100 * 每份值 / 总的值
来计算,整个圆表明100%
。
例如,在咱们的例子数据中,古典音乐能够近似地用26%
来表示。 若是能将这个值恰好显示在对应的份上面就太好了。 要想这样,咱们能够用绘图上下文的fillText(text, x, y)
函数。 这个函数接受三个参数:文本和x
,y
坐标。
怎样计算放置文本的x
和y
坐标呢? 咱们必须动用一些几何知识了,一个叫作极坐标的东西。 通常地,极坐标用半径和角度来定义一个点的位置。 咱们将要用到的两个公式是:
x = R * cos(angle) y = R * sin(angle)
咱们将要应用这个公式,将文本放在饼状图的半径的一半位置与每份角度的一半位置处。 要想作它,咱们须要修改咱们的PieChart类,增长以下代码在if(this.options.doughnutHoleSize){...}
代码块中。
... start_angle = 0; for (categ in this.options.data){ val = this.options.data[categ]; slice_angle = 2 * Math.PI * val / total_value; var pieRadius = Math.min(this.canvas.width/2,this.canvas.height/2); var labelX = this.canvas.width/2 + (pieRadius / 2) * Math.cos(start_angle + slice_angle/2); var labelY = this.canvas.height/2 + (pieRadius / 2) * Math.sin(start_angle + slice_angle/2); if (this.options.doughnutHoleSize){ var offset = (pieRadius * this.options.doughnutHoleSize ) / 2; labelX = this.canvas.width/2 + (offset + pieRadius / 2) * Math.cos(start_angle + slice_angle/2); labelY = this.canvas.height/2 + (offset + pieRadius / 2) * Math.sin(start_angle + slice_angle/2); } var labelText = Math.round(100 * val / total_value); this.ctx.fillStyle = "white"; this.ctx.font = "bold 20px Arial"; this.ctx.fillText(labelText+"%", labelX,labelY); start_angle += slice_angle; } ...
上面代码遍历每份,计算百分比和位置,而后调用fillText()
方法将之绘制到图表上。 咱们用了fillStyle
属性来设置文本颜色为白色,font
属性来设置标签文本的字体、样式和大小。 一样重要,须要注意的是圆环图的doughnutHoleSize
设置后,标签会被往边沿推,以使文本能处于圆环图每份的中央。
如下就是带值标签的图表看起来的样子:
要想完成图表,最后一件事就是为图表添加图例。 咱们的图表图例将会显示数据模型中数据的类别和对应每份的颜色。 首先,咱们须要对index.html
文件作些修改,添加一个<div>
标签用来存储咱们的图例元素。
<html> <body> <canvas id="myCanvas"></canvas> <div id="myLegend"></div> <script type="text/javascript" src="script.js"></script> </body> </html>
而后在script.js
中,咱们添加建立图例元素的代码。 咱们将代码添加在PieChart
类中draw()
函数的末尾。
... if (this.options.legend){ color_index = 0; var legendHTML = ""; for (categ in this.options.data){ legendHTML += "<div><span style='display:inline-block;width:20px;background-color:"+this.colors[color_index++]+";'> </span> "+categ+"</div>"; } this.options.legend.innerHTML = legendHTML; } ...
代码经过传入options
参数来寻找legend
元素。 若是找到,就在其中填上带颜色的块和数据模型类别的名字。
同时,咱们也须要将调用绘值图表的代码改为以下形式:
var myLegend = document.getElementById("myLegend"); var myDougnutChart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"], legend:myLegend } ); myDougnutChart.draw();
这就是结果的图表和图表图例:
咱们看到用HTML5 canvas绘制图表,其实也并非那么困难。 它仅仅须要一点数学和JavaScript知识。 你如今有了要画一个你本身的饼形图和圆环图的所有。
若是你想要一个简便快捷的解决方案,用来建立饼形图和圆环图,同时还有其余类型的图表。你能够下载信息图表和HTML图表标签库或者WordPress插件对应的Charts and Graphs WordPress Visual Designer。
Envato艺云台是数据资产和创造性人才汇聚的全球领先市场平台。全球数百万人都选择经过咱们的市场平台、工做室和课程来购买文件、选聘自由职业者,或者学习建立网站、制做视频、应用、制图等所需的技能。咱们的子网站包括Envato艺云台Tuts+ 网络,全球最大的H五、PS、插图、代码和摄影教程资源库,以及Envato艺云台市场,其中的900多万类数字资产均经过如下七大平台进行销售 - CodeCanyon、ThemeForest、GraphicRiver、VideoHive、PhotoDune、AudioJungle和3DOcean。