摘要:餅狀圖將數(shù)據(jù)用切割成份的圓來展示。至于半徑,我們用寬度的一半與高度的一半的較小值,因?yàn)槲覀儾幌胱岋灎顖D超出。結(jié)果看起來如下這樣繪制圓環(huán)圖我們已經(jīng)看到如何創(chuàng)建餅狀圖。怎樣畫洞呢我們可以畫一個(gè)白色的圓在餅狀圖上。
原文:https://code.tutsplus.com/zh-...
原作:John Negoita
翻譯:Stypstive
在這篇教程中,我將展示用JavaScript和canvas作為手段,在餅狀圖和圓環(huán)圖上顯示數(shù)字信息。
與從零到一創(chuàng)建圖表相比,其實(shí)有更簡(jiǎn)便的方式,例如用CodeCanyon上的這個(gè)圖表庫
但是如果你想知道庫背后的原理,往下讀。
什么是餅狀圖?圖表是用來圖形化展示數(shù)據(jù)的工具。 餅狀圖將數(shù)據(jù)用切割成份的圓來展示。 每份的大小代表了數(shù)據(jù)值所代表的比例大小。
什么是圓環(huán)圖?簡(jiǎn)而言之,圓環(huán)圖是餅狀圖的一個(gè)變種。 不同的是每份切向餅圖的中心,這樣只有輪緣是可見。 就這樣,圖表就如其名一個(gè)圓環(huán)。
開始用Canvas畫繪制餅圖之前, 我們先看看它的組成部分。 我們先看看如何用canvas組件和JavaScript來畫:
一條線
一個(gè)弧度(一個(gè)圓的部分)
一個(gè)顏色填充的圖形
要想用HTML canvas畫它,我們需要先創(chuàng)建幾樣?xùn)|西:
創(chuàng)建一個(gè)項(xiàng)目文件夾,把它命名為piechart-tutorial
在piechart-tutorial文件夾中創(chuàng)建一個(gè)HTML文件index.html 這個(gè)文件中將是HTML代碼。
一個(gè)JS文件scritp.js在piechart-tutorial文件夾中 這個(gè)文件中將是JavaScript代碼。
我們將能簡(jiǎn)就簡(jiǎn),然后添加一下代碼到index.html中:
我們有一個(gè)ID為myCanvas的元素。 然后我們通過標(biāo)簽載入JS代碼。
在script.js中,JS代碼首先獲取一個(gè)canvas的索引,然后設(shè)置canvas的寬和高。 要想在canvas上畫,我們只需要一個(gè)2D上下文,哪里包含著所有的繪圖方法。
var myCanvas = document.getElementById("myCanvas"); myCanvas.width = 300; myCanvas.height = 300; var ctx = myCanvas.getContext("2d");
現(xiàn)在我們已經(jīng)設(shè)置了canvas的寬和高,同時(shí)也獲取了canvas的索引,接下來我們定義一些畫餅狀圖時(shí),需要用到的可重用的函數(shù)。 我們將函數(shù)添加在script.js文件中。
function drawLine(ctx, startX, startY, endX, endY){ ctx.beginPath(); ctx.moveTo(startX,startY); ctx.lineTo(endX,endY); ctx.stroke(); }
函數(shù)drawLine接受5個(gè)參數(shù):
ctx: 指向繪圖上下文的索引
startX:線段起始點(diǎn)的X坐標(biāo)
startY:線段起始點(diǎn)的Y坐標(biāo)
endX:線段結(jié)束點(diǎn)的X坐標(biāo)
endY:線段結(jié)束點(diǎn)的Y坐標(biāo)
我們通過調(diào)用beginPath()來開始劃線。 它通知繪圖上下文,我們要在canvas上畫一些東西了。 我們用moveTo()來設(shè)置起始點(diǎn),調(diào)用lineTo()來表示結(jié)束點(diǎn),然后調(diào)用stoke()來進(jìn)行真正的繪圖。
現(xiàn)在看看我們?nèi)绾萎媹A的一部分,也叫做弧度。
function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle){ ctx.beginPath(); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.stroke(); }
函數(shù)drawArc接受6個(gè)參數(shù):
ctx:指向繪圖上下文的索引
centerX:圓心的X坐標(biāo)
centerY:圓心的Y坐標(biāo)
radius: 圓的半徑
startAngle:部分圓的扇形的開始角度
endAngle: 部分圓的扇形的結(jié)束角度
我們已經(jīng)知道怎樣畫線和弧度了,現(xiàn)在讓我看看如何畫帶顏色的形狀。 由于我們的目標(biāo)是畫一份份組成的餅狀圖,所以我們創(chuàng)建一個(gè)畫餅形圖的份的函數(shù)。
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(); }
函數(shù)drawPieSlice接受7個(gè)參數(shù):
ctx:指向繪圖上下文的索引
centerX:圓心的X坐標(biāo)
centerY:圓心的Y坐標(biāo)
radius:圓的半徑
startAngle:部分圓的扇形的起始角度
endAngle:部分圓的扇形的結(jié)束角度
color:填充的顏色
以下是調(diào)用這三個(gè)函數(shù)的例子:
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");
它將產(chǎn)生如下結(jié)果:
現(xiàn)在,我們有了畫一個(gè)餅形圖的所有必要的工具,讓我們看看如何一起使用它們。
畫餅形圖在概念上,任意圖表都有兩部分:
包含要展示的數(shù)據(jù)的數(shù)據(jù)模型。 這由特定類型的圖表進(jìn)行結(jié)構(gòu)化。
圖形化展示是指按照數(shù)學(xué)公式的規(guī)則,將數(shù)據(jù)模型中的數(shù)據(jù)通過視覺元素來進(jìn)行展示。
餅狀圖數(shù)據(jù)模型
結(jié)構(gòu)化餅狀圖數(shù)據(jù)的方式中,最常用的就是用一系列的類別和對(duì)應(yīng)的值,每個(gè)類別的值與餅圖的份相關(guān)聯(lián)。
例如,餅圖的數(shù)據(jù)模型展示按照流派進(jìn)行分組,看起來就是下面這樣:
古典音樂:10
另類搖滾:14
流行:2
爵士:12
我們可以在script.js文件中添加一個(gè)JS對(duì)象來存儲(chǔ)數(shù)據(jù)模型,如下:
var myVinyls = { "Classical music": 10, "Alternative rock": 14, "Pop": 2, "Jazz": 12 };
餅狀圖的圖形化展示
餅狀圖用圓來顯示數(shù)據(jù)模型中的信息,通過將圓切分成一份份。 每份和數(shù)據(jù)模型中的類別對(duì)應(yīng),每份的大小與對(duì)應(yīng)類別的值成正比。
我的音樂集有四個(gè)類別。 每個(gè)類別在餅形圖中的份數(shù)大小,與它的類別對(duì)應(yīng)的值成正比。
但是我們?cè)鯓佣攘糠輸?shù)的大小? 簡(jiǎn)單--我們通過每份的角度。 我們所需要知道的就是它占360度或者2PI的份數(shù)。 那么半圓就是180deg或者PI,1/4圓90度或PI/2,以此類推。
為了決定每個(gè)類別的份的角度,我們用以下公式:
份角度= 2 * PI * 類別值 / 總值
按照這個(gè)公式,古典音樂的那份近似得到如下角度。 0.526 * PI 或者 94度
讓我開始畫吧。 這次我們將用JavaScript類,將其命名為 PieChart 構(gòu)造函數(shù)接受options做為參數(shù),options包含以下:
canvas:指向我們想要畫餅狀圖的索引
data:盛放數(shù)據(jù)模型的對(duì)象的索引
colors:一個(gè)數(shù)組,數(shù)組中是每份的顏色。
PieChart類同時(shí)也包含一個(gè)draw()方法,它來對(duì)圖表進(jìn)行實(shí)際的繪制。
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參數(shù)進(jìn)行存儲(chǔ)。 它保存了canvas的索引,同時(shí)也創(chuàng)建一個(gè)繪畫上下文作為類成員變量。 然后它存儲(chǔ)了options中的colors數(shù)組。
接下來的部分是最根本的,函數(shù)draw()。 它會(huì)從數(shù)據(jù)模型中提取數(shù)據(jù)。 首先,它計(jì)算數(shù)據(jù)模型中所有數(shù)據(jù)值的和。 然后對(duì)其中每個(gè)類別應(yīng)用上面提到的計(jì)算角度的函數(shù)。 最后我們調(diào)用drawPieSlice()函數(shù),用canvas的中心作為餅狀圖的中心。 至于半徑,我們用canvas寬度的一半與canvas高度的一半的較小值,因?yàn)槲覀儾幌胱岋灎顖D超出canvas。
同樣,每次畫一個(gè)類別時(shí),要偏移每份的起始角度和結(jié)束角度,否則會(huì)發(fā)生重疊。
要想使用類,我們必須先創(chuàng)建一個(gè)實(shí)例對(duì)象,然后在創(chuàng)建的對(duì)象上調(diào)用draw()方法。
var myPiechart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"] } ); myPiechart.draw();
結(jié)果看起來如下這樣:
繪制圓環(huán)圖我們已經(jīng)看到如何創(chuàng)建餅狀圖。 同樣我們看到,圓環(huán)圖與餅狀圖不同之處僅在于中間多了一個(gè)洞。 怎樣畫洞呢? 我們可以畫一個(gè)白色的圓在餅狀圖上。
讓我們通過修改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參數(shù)中,通過一個(gè)doughnutHoleSize成員變量。 如果這個(gè)參數(shù)在options中沒有傳,代碼就按照之前的進(jìn)行繪制,如果傳了,就在餅狀圖中心畫一個(gè)白色的圓形。
圓的半徑由餅形圖的半徑和doughnutHoleSize參數(shù)的乘積來決定。 它應(yīng)該是0到1之間的數(shù)字,0代表餅形圖,大于0時(shí),值越大餅形圖中間的洞越大,當(dāng)值為1時(shí)會(huì)使圖表不可見。
要想畫一個(gè)圖表一半大小的圓環(huán)圖,我們可以將doughnutHoleSize設(shè)置為0.5,然后像下面這樣調(diào)用:
var myDougnutChart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"], doughnutHoleSize:0.5 } ); myDougnutChart.draw();
以下是結(jié)果:
添加標(biāo)簽和圖表圖例我們的餅狀圖表和圓環(huán)圖表看起來挺棒了,但是它會(huì)變得更棒,通過添加兩樣?xùn)|西:
值標(biāo)簽:顯示每份對(duì)應(yīng)的百分比
圖表圖例:顯示圖表中每個(gè)類別和顏色的對(duì)應(yīng)關(guān)系
通常,每份的值用百分比來表示,通過100 * 每份值 / 總的值來計(jì)算,整個(gè)圓代表100%。
例如,在我們的例子數(shù)據(jù)中,古典音樂可以近似地用26%來表示。 如果能將這個(gè)值剛好顯示在對(duì)應(yīng)的份上面就太好了。 要想這樣,我們可以用繪圖上下文的fillText(text, x, y)函數(shù)。 這個(gè)函數(shù)接受三個(gè)參數(shù):文本和x,y坐標(biāo)。
怎樣計(jì)算放置文本的x和y坐標(biāo)呢? 我們必須動(dòng)用一些幾何知識(shí)了,一個(gè)叫做極坐標(biāo)的東西。 一般地,極坐標(biāo)用半徑和角度來定義一個(gè)點(diǎn)的位置。 我們將要用到的兩個(gè)公式是:
x = R * cos(angle) y = R * sin(angle)
我們將要應(yīng)用這個(gè)公式,將文本放在餅狀圖的半徑的一半位置與每份角度的一半位置處。 要想做它,我們需要修改我們的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; } ...
上面代碼遍歷每份,計(jì)算百分比和位置,然后調(diào)用fillText()方法將之繪制到圖表上。 我們用了fillStyle屬性來設(shè)置文本顏色為白色,font屬性來設(shè)置標(biāo)簽文本的字體、樣式和大小。 同樣重要,需要注意的是圓環(huán)圖的doughnutHoleSize設(shè)置后,標(biāo)簽會(huì)被往邊沿推,以使文本能處于圓環(huán)圖每份的中央。
以下就是帶值標(biāo)簽的圖表看起來的樣子:
要想完成圖表,最后一件事就是為圖表添加圖例。 我們的圖表圖例將會(huì)顯示數(shù)據(jù)模型中數(shù)據(jù)的類別和對(duì)應(yīng)每份的顏色。 首先,我們需要對(duì)index.html文件做些修改,添加一個(gè) 然后在script.js中,我們添加創(chuàng)建圖例元素的代碼。 我們將代碼添加在PieChart類中draw()函數(shù)的末尾。 代碼通過傳入options參數(shù)來尋找legend元素。 如果找到,就在其中填上帶顏色的塊和數(shù)據(jù)模型類別的名字。 同時(shí),我們也需要將調(diào)用繪值圖表的代碼改成如下形式: 這就是結(jié)果的圖表和圖表圖例: 我們看到用HTML5 canvas繪制圖表,其實(shí)也并不是那么困難。 它僅僅需要一點(diǎn)數(shù)學(xué)和JavaScript知識(shí)。 你現(xiàn)在有了要畫一個(gè)你自己的餅形圖和圓環(huán)圖的全部。 如果你想要一個(gè)簡(jiǎn)便快捷的解決方案,用來創(chuàng)建餅形圖和圓環(huán)圖,同時(shí)還有其他類型的圖表。你可以下載信息圖表和HTML圖表標(biāo)簽庫或者WordPress插件對(duì)應(yīng)的Charts and Graphs WordPress Visual Designer。 Envato藝云臺(tái)是數(shù)據(jù)資產(chǎn)和創(chuàng)造性人才匯聚的全球領(lǐng)先市場(chǎng)平臺(tái)。全球數(shù)百萬人都選擇通過我們的市場(chǎng)平臺(tái)、工作室和課程來購買文件、選聘自由職業(yè)者,或者學(xué)習(xí)創(chuàng)建網(wǎng)站、制作視頻、應(yīng)用、制圖等所需的技能。我們的子網(wǎng)站包括Envato藝云臺(tái)Tuts+ 網(wǎng)絡(luò),全球最大的H5、PS、插圖、代碼和攝影教程資源庫,以及Envato藝云臺(tái)市場(chǎng),其中的900多萬類數(shù)字資產(chǎn)均通過以下七大平臺(tái)進(jìn)行銷售 - CodeCanyon、ThemeForest、GraphicRiver、VideoHive、PhotoDune、AudioJungle和3DOcean。 文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。 轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/88277.html
...
if (this.options.legend){
color_index = 0;
var legendHTML = "";
for (categ in this.options.data){
legendHTML += "
var myLegend = document.getElementById("myLegend");
var myDougnutChart = new Piechart(
{
canvas:myCanvas,
data:myVinyls,
colors:["#fde23e","#f16e23", "#57d9ff","#937e88"],
legend:myLegend
}
);
myDougnutChart.draw();
摘要:適用于,演示這是開發(fā)的一個(gè)簡(jiǎn)單的可視化庫,它允許你創(chuàng)建所有常用的圖表類型條形圖,樹形圖,折線圖,面積圖等??梢暂p松地對(duì)折線圖和條形圖進(jìn)行混合和匹配以組合不同的數(shù)據(jù)集,這是非常棒的功能。 翻譯:瘋狂的技術(shù)宅原文:https://www.monterail.com/blo... 本文首發(fā)微信公眾號(hào):jingchengyideng歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章 你的程序有多...
閱讀 1324·2021-11-16 11:45
閱讀 2249·2021-11-02 14:40
閱讀 3888·2021-09-24 10:25
閱讀 3035·2019-08-30 12:45
閱讀 1267·2019-08-29 18:39
閱讀 2481·2019-08-29 12:32
閱讀 1617·2019-08-26 10:45
閱讀 1927·2019-08-23 17:01