学完我写的上一章小白上学canvas基础,我们就来这里现学现用了。这里先看我们的设计图和最终实现效果;
左面是设计稿,右面是完成后的效果图:
没办法和原图一模一样。文字下方数字正的,我的是倒着的;
此图难点:扇形,圆形头像,弧形文字
话不多说直接上代码:
<!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的宽高来写。
绘制完图片(头像)会覆盖整个画布,所以图片得最后绘制。
弧形文字需要一点一旦调整弧度。
留言:如有疑问关注我给我留言,我们一起成为大牛!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。