附:canvas饼图2

设计图:image.png
这两天产品经理交待了几个活,其中需要画以下两个饼图,没有找到类似UI的图表库,只能自己画。本次画的是左边这个。

最终效果如下:
image.png

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>

image.png

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(); 

效果如下:
image.png

在这里要注意的是:
画圆的arc方法
image.png
它的counterclockwise参数,如果true逆时针,会正时针会到的结果相反,所以在这里用1-比例,得到相反的比例。

并且image.png
我想要开始的角度在正上方,那么开始和结束角都要加上1.5

  1. 画女指引线
//女 指引线
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
        }
}; 

image.png

最后,另外的步骤和以上就差不多了。就不细说了,上全部代码

<!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>

andy
6 声望3 粉丝

贪财好色!经不住诱惑!