學完我寫的上一章小白上學canvas基礎,咱們就來這裏現學現用了。這裏先看咱們的設計圖和最終實現效果;
左面是設計稿,右面是完成後的效果圖:css
沒辦法和原圖如出一轍。文字下方數字正的,個人是倒着的;
此圖難點:扇形,圓形頭像,弧形文字
話很少說直接上代碼:html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <style> html,body{background: #273341;} #mycanvas{} .pie{width: 320px;height: 320px;margin: 0 auto;} img{width: 100%;display: none} .economy{text-align: center;transform: rotate(45deg);color: #fff;font-family: "微軟雅黑";font-size: 14px;} </style> <body> <div class="pie"> <canvas id="canvas" width="960" height="960" style="width:320px;height:320px;"></canvas> </div> <!-- canvas的畫布寬高(分辨率)是width和height,而style中的寬高是canvas在頁面中顯示的寬高,畫布分辨率越高,繪製出來的圖任意縮放也不會出現很大的鋸齒 --> </body> <script> var canvas = document.getElementById('canvas'); var r2=380,r1=480; var ctx = canvas.getContext('2d'); if (canvas.getContext){ var circle = {x: 480, y: 480, radius: 442} var smccircle = {x: 480, y: 480, radius: 342} //背景色 ctx.fillStyle = '#273341'; ctx.fillRect(0,0,960,960); ctx.fill(); //外彩色扇形背景圓1 ites(0,360,480,'#323d4b'); //彩色外扇葉 ites(0,30,r1,'#4c17e2');//>0 ites(45,55,r1,'#1777e2');//>45 ites(90,110,r1,'#17cde2');//>90 ites(135,146,r1,'#3fc371');//>135 ites(180,198,r1,'#ffbc3a');//>180 ites(225,231,r1,'#e27217');//>225 ites(270,290,r1,'#e217a1');//>270 ites(315,335,r1,'#b017e2');//>315&<360 //內覆蓋扇形背景圓1 ites(0,360,400,'#273341'); //彩色內扇葉 ites(0,45,r2,'#4c17e2'); ites(45,90,r2,'#1777e2'); ites(90,135,r2,'#17cde2'); ites(135,180,r2,'#3fc371'); ites(180,225,r2,'#ffbc3a'); ites(225,270,r2,'#e27217'); ites(270,315,r2,'#e217a1'); ites(315,360,r2,'#b017e2'); //內覆蓋扇形背景圓2 ites(0,360,300,'#273341'); //交叉背景線 line(0,480,960,480); line(480,0,480,960); line(0,0,960,960); line(960,0,0,960); ctx.arc(480,480,r2,0,rads(45),false); ctx.save(); //頭像邊框 drawCircularText(smccircle,'水分', rads(18), rads(28),'center'); drawCircularText(smccircle,'蛋白質', rads(58), rads(78),'center'); drawCircularText(smccircle,'內臟脂肪', rads(98), rads(127),'center'); drawCircularText(smccircle,'骨骼', rads(153), rads(163),'center'); drawCircularText(smccircle,'基礎代謝', rads(188), rads(216),'center'); drawCircularText(smccircle,'BMI', rads(241), rads(253),'center'); drawCircularText(smccircle,'脂肪', rads(287), rads(298),'center'); drawCircularText(smccircle,'肌肉', rads(333), rads(343),'center'); ctx.restore(); var v = 'left'; drawCircularText(circle,'60.5%', rads(24), rads(38),v); drawCircularText(circle,'17.8%', rads(69), rads(83),v); drawCircularText(circle,' 6', rads(114), rads(130),v); drawCircularText(circle,' 4.3', rads(159), rads(175),v); drawCircularText(circle,' 1570', rads(204), rads(220),v); drawCircularText(circle,' 21.6', rads(249), rads(265),v); drawCircularText(circle,'17.1%', rads(294), rads(308),v); drawCircularText(circle,'55.5%', rads(339), rads(353),v); // Create a circular clipping path ctx.translate(480,480); ctx.beginPath(); ctx.arc(0,0,160,0,Math.PI*2,true); ctx.closePath(); ctx.strokeStyle="#ffbc3a"; ctx.lineWidth =16; ctx.stroke(); ctx.clip(); var img = new Image(); img.src='css/img/head.png'; img.onload = function(){ ctx.drawImage(img,-160,-160,320,320); } } //轉換弧度 function rads(x){ return Math.PI*x/180; } //圓 function ites(a,b,r,color){ ctx.beginPath(); ctx.moveTo(480,480); ctx.arc(480,480,r,rads(a),rads(b),false); ctx.closePath(); ctx.fillStyle = color; ctx.fill(); } //線 function line(a,b,c,d){ ctx.beginPath(); ctx.moveTo(a,b); ctx.lineTo(c,d); ctx.strokeStyle="#273341"; ctx.closePath(); ctx.lineWidth =10; ctx.stroke(); } function siner(a,b,deg,font){ ctx.save(); ctx.fillStyle = '#fff' ctx.textAlign = "center"; ctx.font = '48px 微軟雅黑'; ctx.translate(a, b); ctx.rotate(rads(deg)) ctx.fillText(font, 0, 0); ctx.restore(); } function drawCircularText(s,string, startAngle, endAngle ,lv){ var radius = s.radius, angleDecrement = (startAngle - endAngle)/(string.length-1), angle = parseFloat(startAngle), index = 0, character; ctx.save(); ctx.fillStyle = 'white'; ctx.font = '40px 微軟雅黑'; ctx.textAlign = lv; ctx.textBaseline = 'middle'; while (index < string.length) { character = string.charAt(index); ctx.save(); ctx.beginPath(); ctx.translate(s.x + Math.cos(angle) * radius, s.y + Math.sin(angle) * radius); ctx.rotate(Math.PI/2 + angle); ctx.fillText(character, 0, 0); // ctx.strokeText(character, 0, 0); angle -= angleDecrement; index++; ctx.restore(); } ctx.restore(); } /*//H繪製圓形頭像 // var ctx = document.getElementById('canvas').getContext('2d'); // ctx.fillRect(0,0,240,240); ctx.translate(120,120); // Create a circular clipping path ctx.beginPath(); ctx.arc(0,0,40,0,Math.PI*2,true); ctx.clip(); // draw background var lingrad = ctx.createLinearGradient(0,-240,0,240); lingrad.addColorStop(0, '#232256'); lingrad.addColorStop(1, '#143778'); ctx.fillStyle = lingrad; ctx.fillRect(-75,-75,150,150); var img = new Image(); img.src='css/img/head.jpg'; img.onload = function(){ ctx.drawImage(img,-40,-40,80,80); }*/ </script> </html>
上面的代碼直接複製進你的html文件裏打開就能看到效果。
注意事項:
開始時按240像素大小的畫布寫,最後發現放在分辨率高的手機上全是鋸齒,因此最後採用960的寬高來寫。
繪製完圖片(頭像)會覆蓋整個畫布,因此圖片得最後繪製。
弧形文字須要一點一旦調整弧度。
留言:若有疑問關注我給我留言,咱們一塊兒成爲大牛!canvas