学完我写的上一章小白上学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