摘要:圖表是數(shù)據(jù)表示的一種直觀的形式,前端開(kāi)發(fā)經(jīng)常回合圖表打交道,一般都會(huì)借用第三方的庫(kù),如等,但如果只是很簡(jiǎn)單的圖標(biāo),我們完全可以自己繪制,現(xiàn)在我們來(lái)繪制一個(gè)簡(jiǎn)單的百分比展示圖表最終效果如下代碼額,很簡(jiǎn)單,隨便放在某個(gè)地方分析從最終效果來(lái)看,這
圖表是數(shù)據(jù)表示的一種直觀的形式,前端開(kāi)發(fā)經(jīng)常回合圖表打交道,一般都會(huì)借用第三方的js庫(kù),如echats、bizchats等,
但如果只是很簡(jiǎn)單的圖標(biāo),我們完全可以自己繪制,現(xiàn)在我們來(lái)繪制一個(gè)簡(jiǎn)單的百分比展示圖表
額,很簡(jiǎn)單,隨便放在html某個(gè)地方
分析從最終效果來(lái)看,這個(gè)圖表由6部分組成
1.最大的外圈
2.最中心向外的內(nèi)二圈
3.最里面的內(nèi)圈
4.帶顏色的多個(gè)圓弧組成的彩圈
5.中心的指針
6.數(shù)字文字
下來(lái)就按照順序繪制出來(lái)
配置首先還是寫(xiě)一些可配置的變量
let r = 100, //半徑 cx = 0, //圓心位置 cy = 0, parts = [ //彩條 "#78C77C","#F3D263","#FC9136","#FB574A","#AE1A51","#8F66DD" ], texts = [ //文字段落 0,30,60,90,120,150 ], pad = 1/100, //間隙 data = 0.5 //數(shù)據(jù),百分比,20%應(yīng)寫(xiě)成0.2初始化
let canvas = document.getElementById("chart") canvas.width = 262; canvas.height = 262; let ctx = canvas.getContext("2d") ctx.translate(canvas.width/2,canvas.height/2); ctx.save() ctx.rotate(0.5*Math.PI)
為什么要旋轉(zhuǎn)0.5π呢,因?yàn)闉榱吮阌谟?jì)算,需要把圓的起始位置轉(zhuǎn)至最下
繪制-外圈ctx.beginPath() ctx.arc(cx,cy,r+30,0,2*Math.PI) ctx.fillStyle="#fff" ctx.strokeStyle="gray" ctx.shadowOffsetX = 0; // 陰影Y軸偏移 ctx.shadowOffsetY = 0; // 陰影X軸偏移 ctx.shadowBlur = 1; // 模糊尺寸 ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; // 顏色 ctx.stroke(); ctx.fill();效果 繪制-內(nèi)二圈
ctx.beginPath() ctx.arc(cx,cy,r-20,0,2*Math.PI) ctx.fillStyle="#F2F1F3" ctx.fill();效果 注意
為什么不先繪制最內(nèi)層的圈,因?yàn)閏anvas的層級(jí)關(guān)系是后來(lái)者居上,所以有重疊的部分最上面的圖形最后繪制
繪制-內(nèi)圈ctx.beginPath() ctx.arc(cx,cy,r-20-30,0,2*Math.PI) ctx.fillStyle="#fff" ctx.strokeStyle="#fff" ctx.stroke(); ctx.fill();效果 繪制-彩圈
這里可以理解為多個(gè)同心圓弧,把2π等分,中間有相同的間隔
let startRad = 0 let partRad = ( 2 - (pad*parts.length) ) / parts.length parts.forEach((color,index)=>{ if (index===0) { startRad += pad/2 } else { startRad += pad + partRad } ctx.beginPath() ctx.strokeStyle = color ctx.lineWidth = 20 ctx.arc(cx,cy,r,startRad * Math.PI,(startRad+partRad)*Math.PI) ctx.stroke() }) ctx.restore();注意
1.等分2π的時(shí)候別忘了間隔
2.下一個(gè)圓弧的起始點(diǎn)是上一個(gè)圓弧的終點(diǎn)加上間隔
ctx.save(); ctx.rotate(data*2*Math.PI) ctx.beginPath() ctx.moveTo(-6,0) ctx.lineTo(0,r-30) ctx.lineTo(6,0) ctx.closePath(); ctx.fillStyle = "#4394F8"; ctx.fill(); ctx.beginPath() ctx.arc(0,0,10,0,2*Math.PI) ctx.fillStyle = "#F4F6F9"; ctx.strokeStyle = "gray" ctx.strokeWidth = 1 ctx.shadowOffsetX = 0; // 陰影Y軸偏移 ctx.shadowOffsetY = 0; // 陰影X軸偏移 ctx.shadowBlur = 10; // 模糊尺寸 ctx.shadowColor = "#F4F6F9"; // 顏色 ctx.stroke() ctx.fill(); ctx.restore();注意
1.指針由2部分構(gòu)成,中心的圓形和三角形
2.注意是圓形在上,三角形在下,所以最后繪制圓形
ctx.save() ctx.rotate(0.5*Math.PI) let beginRotate = 0, textPartRad = 2/(texts.length) texts.forEach((text,index)=>{ if (index!=0) { beginRotate = beginRotate + textPartRad } ctx.save(); ctx.beginPath() ctx.font = "15px" ctx.textAlign = "center" ctx.textBaseline = "middle" ctx.translate(cx+Math.cos(beginRotate*Math.PI)*(r-35),cy+Math.sin(beginRotate*Math.PI)*(r-35)); ctx.rotate(beginRotate*Math.PI+(-0.5*Math.PI)) ctx.rotate(Math.PI) ctx.fillText(text,0,0) ctx.restore(); }) ctx.restore();注意
1.每個(gè)文字先放到最中間(0,0)
2.然后根據(jù)圓的半徑和文字放置地點(diǎn)的旋轉(zhuǎn)角度,通過(guò)三角函數(shù)計(jì)算出位置,然后移動(dòng)
3.根據(jù)旋轉(zhuǎn)角度將文字旋轉(zhuǎn)到合適位置
Chart
還有許多可以優(yōu)化的地方,如代碼中顏色,局部位置的距離等等,可以做成配置項(xiàng),有時(shí)間在優(yōu)化吧^_^
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106141.html
摘要:新公司已經(jīng)呆了一個(gè)多月,目前著手一個(gè)數(shù)據(jù)可視化的項(xiàng)目,數(shù)據(jù)可視化肯定要用到圖形庫(kù)如等,經(jīng)決定我的這個(gè)項(xiàng)目用阿里旗下螞蟻金服所開(kāi)發(fā)的圖表庫(kù)。數(shù)據(jù)提示框內(nèi)提示的信息還可以通過(guò)格式化函數(shù)動(dòng)態(tài)指定。 新公司已經(jīng)呆了一個(gè)多月,目前著手一個(gè)數(shù)據(jù)可視化的項(xiàng)目,數(shù)據(jù)可視化肯定要用到圖形庫(kù)如D3、Highcharts、ECharts、Chart等,經(jīng)決定我的這個(gè)項(xiàng)目用阿里旗下螞蟻金服所開(kāi)發(fā)的G2圖表庫(kù)。...
閱讀 1919·2021-09-22 15:29
閱讀 3391·2019-08-30 15:44
閱讀 3592·2019-08-30 15:43
閱讀 1792·2019-08-30 13:48
閱讀 1516·2019-08-29 13:56
閱讀 2511·2019-08-29 12:12
閱讀 1001·2019-08-26 11:35
閱讀 1076·2019-08-26 10:25