完成效果如下:
一、绘制静态饼图
step1 设置圆心坐标,半径进行绘制大圆和小圆
<canvas id="myCanvas" width="600" height="600"></canvas>
复制代码
css
canvas {
border: 1px solid #ccc;
}
复制代码
js
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d');
var cX = canvas.width / 2; //圆心X坐标
var cY = canvas.height / 2; //圆心Y坐标
var bR = 200; //设置大圆半径
var sR = 100; //设置小圆半径
// step1 创建大圆
context.beginPath();
context.arc(cX, cY, bR, 0, 2 * Math.PI);
context.fillStyle = 'red';
context.fill();
// step2 创建小圆
context.beginPath();
context.arc(cX, cY, sR, 0, 2 * Math.PI);
context.fillStyle = 'white';
context.fill();
复制代码
step2 绘制45°扇形
// step1 创建大圆
context.beginPath();
context.moveTo(cX, cY);
context.lineTo(cX + bR, cY);
context.arc(cX, cY, bR, 0, 1 / 8 * 2 * Math.PI); //绘制45°圆
context.lineTo(cX, cY);
context.fillStyle = 'red';
context.fill();
// step2 创建小圆
context.beginPath();
context.moveTo(cX, cY);
context.lineTo(cX + sR, cY);
context.arc(cX, cY, sR, 0, 1 / 8 * 2 * Math.PI); //绘制45°圆
context.lineTo(cX, cY);
context.fillStyle = 'white';
context.fill();
复制代码
以上代码存在个问题(js小数点的问题),如下图,小圆未把大圆区域全部填充完全,边缘存在红色虚线
context.strokeStyle = "white";
context.stroke();
context.lineWidth = 2;
复制代码
step3 把大圆、小圆的代码进行封装,目的为了创建多个不同弧度的扇形时方便调用
function drawDonuts(startAngle, endAngle, color) {
// step1 创建大圆
context.beginPath();
context.moveTo(cX, cY);
context.lineTo(cX + bR * Math.cos(startAngle), cY + bR * Math.sin(startAngle));
context.arc(cX, cY, bR, startAngle, endAngle);
context.lineTo(cX, cY);
context.fillStyle = color;
context.fill();
// step2 创建小圆
context.beginPath();
context.moveTo(cX, cY);
context.lineTo(cX + sR * Math.cos(startAngle), cY + sR * Math.sin(startAngle));
context.arc(cX, cY, sR, startAngle, endAngle);
context.lineTo(cX, cY);
context.fillStyle = 'pink';
context.fill();
// 添加以下代码是为 解决小圆未把大圆区域全部填充完全的问题,如上图所示边缘存在红色虚线
context.strokeStyle = "pink";
context.stroke();
context.lineWidth = 2;
}
复制代码
// 设置每个扇形的弧度比例以及颜色
var setArr = [{
scale: 0.2 * 2 * Math.PI,
color: "red"
}, {
scale: 0.35 * 2 * Math.PI,
color: "cyan"
}, {
scale: 0.25 * 2 * Math.PI,
color: "purple"
}, {
scale: 0.1 * 2 * Math.PI,
color: "blue"
}, {
scale: 0.1 * 2 * Math.PI,
color: "orange"
}];
var startAngle = 0;
var endAngle = 0;
for(var i =0;i<setArr.length;i++){
endAngle += setArr[i].scale;
drawDonuts(startAngle,endAngle,setArr[i].color); //调用封装函数
startAngle = endAngle;
}
复制代码
二、动态实现
step1 实现纯色甜甜圈动画显示
注释该段代码
// for(var i =0;i<setArr.length;i++){
// endAngle += setArr[i].scale;
// drawDonuts(startAngle,endAngle,setArr[i].color);
// startAngle = endAngle;
// }
var speed = 5 / 360 * 2 * Math.PI; //控制动态显示的速度
var timer1 = setInterval(function() {
if (endAngle > 2 * Math.PI) {
clearInterval(timer1); //优化性能,不再继续渲染
}
endAngle += speed;
drawDonuts(startAngle, endAngle, 'cyan');
startAngle = endAngle;
}, 1000 / 40);
复制代码
step2 实现不同颜色甜甜圈动效显示
var speed = 5 / 360 * 2 * Math.PI; //控制动态显示的速度
var dataArr = [0];
var sum = 0;
for (var i = 0; i < setArr.length; i++) {
sum += setArr[i].scale;
dataArr.push(sum);
}
var timer1 = setInterval(function() {
endAngle += speed;
if (endAngle > 2 * Math.PI) {
clearInterval(timer1); //优化性能,不再继续渲染
}
for (var i = 1; i < dataArr.length; i++) {
if (endAngle >= dataArr[i - 1] && endAngle <= dataArr[i]){
drawDonuts(startAngle, endAngle, setArr[i - 1].color);
break;
}
}
startAngle = endAngle - 0.01; //处理动效旋转时出现的间隙问题
}, 1000 / 40);
复制代码
大功告成 —— ending
太少写文章,表达不大好,欢迎大家提宝贵意见~感激~