canvas 饼图动效

完成效果如下:

一、绘制静态饼图

step1 设置圆心坐标,半径进行绘制大圆和小圆

html

<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

太少写文章,表达不大好,欢迎大家提宝贵意见~感激~

转载于:https://juejin.im/post/5c36a3fd518825253208eb50

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值