设计图:
这两天产品经理交待了几个活,其中需要画以下两个饼图,没有找到类似UI的图表库,只能自己画。本次画的是左边这个。
最终效果如下:
1.相应的基础代码
先按照设计稿画最外层的虚线
并且先假设我们有一个数据 data
<style>
*{margin:0;padding:0;}
#box{background:#03156d;width:800px;height:500px;margin:100px auto;}
</style>
<div id="box">
<canvas id="c1" width="800" height="500"></canvas>
</div>
<script>
var data={
"女":0.6,
"男":0.4
};
var w=800,h=500,center={x:w/2,y:h/2};
var oC1=document.getElementById('c1');
var ctx=oC1.getContext('2d');
var locations={}; //记录上次位置
var dottedDiameter=400; //虚线直径
ctx.setLineDash([5]); //设置虚线
ctx.strokeStyle="#D8D8D8";
ctx.beginPath(); //起始一条路径,或重置当前路径
ctx.arc(center.x,center.y,dottedDiameter/2,0,Math.PI*2,true);//创建弧/曲线(用于创建圆形或部分圆)
ctx.stroke();
</script>
2.画红圈
var redDiameter=dottedDiameter-40, //红直径 上下各20的间距
redWidth=50; //红宽度
ctx.setLineDash([]); //取消虚线
ctx.strokeStyle="#DA367B";
ctx.lineWidth=redWidth;
ctx.beginPath(); //起始一条路径,或重置当前路径
//1.起始角本来是0,改成1.5的位置后,结束角也要另上。
//2.true 逆时针画圆后。应该用1-比例 具体看一下 arc的 counterclockwise
let start=Math.PI*1.5,
end=Math.PI*(2*(1-data['女'])+1.5);
ctx.arc(center.x,center.y,redDiameter/2-redWidth/2,start,end,true);
ctx.stroke();
效果如下:
在这里要注意的是:
画圆的arc方法
它的counterclockwise参数,如果true逆时针,会正时针会到的结果相反,所以在这里用1-比例,得到相反的比例。
并且
我想要开始的角度在正上方,那么开始和结束角都要加上1.5
- 画女指引线
//女 指引线
var XY=getXY(240,dottedDiameter/2);
ctx.strokeStyle="#535583";
ctx.lineWidth=2;
ctx.beginPath();
locations.x=center.x+XY.x;
locations.y=center.y+XY.y;
ctx.moveTo(locations.x,locations.y);
locations.x-=70; //左移70
ctx.lineTo(locations.x,locations.y);
XY=getXY(360-30,60);
locations.x+=XY.x;
locations.y+=XY.y;
ctx.lineTo(locations.x,locations.y);
ctx.stroke();
ctx.textAlign='center';
ctx.fillStyle='#D8D8D8';
ctx.font='24px Arial';
ctx.fillText('女',locations.x,locations.y-20);
function getXY(angle,radius){ //通过正余弦区取XY坐标
return {
x:Math.sin((180-angle)*Math.PI/180)*radius,
y:Math.cos((180-angle)*Math.PI/180)*radius
}
};
最后,另外的步骤和以上就差不多了。就不细说了,上全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>andy-js:canvas饼图1</title>
<style>
*{margin:0;padding:0;}
#box{background:#03156d;width:800px;height:500px;margin:100px auto;}
</style>
</head>
<body>
<div id="box">
<canvas id="c1" width="800" height="500"></canvas>
</div>
<script>
var data={
"女":0.6,
"男":0.4
};
var w=800,h=500,center={x:w/2,y:h/2};
var oC1=document.getElementById('c1');
var ctx=oC1.getContext('2d');
var locations={}; //记录上次位置
var dottedDiameter=400; //虚线直径
ctx.setLineDash([5]); //设置虚线
ctx.strokeStyle="#D8D8D8";
ctx.beginPath(); //起始一条路径,或重置当前路径
ctx.arc(center.x,center.y,dottedDiameter/2,0,Math.PI*2,true);//创建弧/曲线(用于创建圆形或部分圆)
ctx.stroke();
//红圈 女
var redDiameter=dottedDiameter-40, //红直径 上下各20的间距
redWidth=50; //红宽度
ctx.setLineDash([]); //取消虚线
ctx.strokeStyle="#DA367B";
ctx.lineWidth=redWidth;
ctx.beginPath(); //起始一条路径,或重置当前路径
//1.起始角本来是0,改成1.5的位置后,结束角也要另上。
//2.true 逆时针画圆后。应该用1-比例 具体看一下 arc的 counterclockwise
let start=Math.PI*1.5,
end=Math.PI*(2*(1-data['女'])+1.5);
ctx.arc(center.x,center.y,redDiameter/2-redWidth/2,start,end,true);
ctx.stroke();
//女 指引线
var XY=getXY(240,dottedDiameter/2);
ctx.strokeStyle="#535583";
ctx.lineWidth=2;
ctx.beginPath();
locations.x=center.x+XY.x;
locations.y=center.y+XY.y;
ctx.moveTo(locations.x,locations.y);
locations.x-=70; //左移70
ctx.lineTo(locations.x,locations.y);
XY=getXY(360-30,60);
locations.x+=XY.x;
locations.y+=XY.y;
ctx.lineTo(locations.x,locations.y);
ctx.stroke();
ctx.textAlign='center';
ctx.fillStyle='#D8D8D8';
ctx.font='24px Arial';
ctx.fillText('女',locations.x,locations.y-20);
function getXY(angle,radius){ //通过正余弦区取XY坐标
return {
x:Math.sin((180-angle)*Math.PI/180)*radius,
y:Math.cos((180-angle)*Math.PI/180)*radius
}
};
//蓝圈 男
var blueDiameter=redDiameter-20, //蓝直径 上下各10的间距
blueWidth=40;
ctx.strokeStyle="#0862e7";
ctx.lineWidth=blueWidth;
ctx.beginPath();
ctx.arc(center.x,center.y,blueDiameter/2-blueWidth/2,end,start,true); //开始结束与上一个圈相反
ctx.stroke();
//男 指引线
var XY=getXY(60,dottedDiameter/2);
ctx.strokeStyle="#535583";
ctx.lineWidth=2;
ctx.beginPath();
locations.x=center.x+XY.x;
locations.y=center.y+XY.y;
ctx.moveTo(locations.x,locations.y);
locations.x+=70; //左移70
ctx.lineTo(locations.x,locations.y);
XY=getXY(180-30,60);
locations.x+=XY.x;
locations.y+=XY.y;
ctx.lineTo(locations.x,locations.y);
ctx.stroke();
ctx.textAlign='center';
ctx.fillStyle='#D8D8D8';
ctx.font='24px Arial';
ctx.fillText('男',locations.x,locations.y+40);
</script>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。