新项目场景中饼图的两种动效——恒生寻常问道实习记录

项目场景:

要求饼图有一个动态绘制过程,从0°开始旋转一周,一个接一个的显示每一模块,如图所示:
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述


问题描述

一开始通过for循环写的动效效果与需求不符,通过该逻辑呈现的效果是所有模块一起出现,一起增加的效果,如下图所示:

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

原因分析:

问题效果代码如下:

if (this.chartConfig.canvasSpeed > 0) {		//编写好的图表组件,其中动效时间大于0时  canvasSpeed(0~1)进程,0代表未开始,1代表动效结束
        //动效画饼图
        let sAngle = this.chartConfig.circleData[0].startAngle;		//sAngle为第一个模块的初始角度
        for (let i = 0; i < this.chartConfig.circleData.length; ++i) {
          const dist =
            this.chartConfig.circleData[i].endAngle - this.chartConfig.circleData[i].startAngle;		//dist为每个模块的角度
          const ring = {	//饼图每一模块的一些属性(颜色,圆心位置等)
            color: this.chartConfig.circleData[i].color,
            x: this.chartConfig.centerX,
            y: this.chartConfig.centerY,
            r: this.chartConfig.radius,
            sAngle: sAngle,		//每一模块的起始位置
            eAngle: sAngle + dist * this.chartConfig.canvasSpeed, //需要根据canvasSpeed(0~1)计算,每一模块现在正在画的角度(起始角度+每一模块角度*动效进程)
            lineWidth: this.chartConfig.lineWidth,
            counterclockwise: this.chartConfig.counterclockwise,
          };
          sAngle = ring.eAngle;		//让后一模块的起始角度为前一模块的结束角度
          this.$draw.drawSimpleRing(this.ctx, ring);	//绘制饼图
        }
      }

因为该方法会直接跑完整个for循环,从而导致所有模块部分会同时一起绘制,而不会同所想要的需求一样,等一个模块画完之后再继续画下一个模块。


解决方案:

换了一种逻辑,通过while循环编写,代码如下:

if (this.chartConfig.canvasSpeed > 0) {		//编写好的图表组件,其中动效时间大于0时  canvasSpeed(0~1)进程,0代表未开始,1代表动效结束
        //动效画饼图
        let angles = new Array();	//定义一个数组,存放每一个模块的角度
        for (let i = 0; i < this.chartConfig.circleData.length; ++i) {	//通过for循环将每一个模块的角度存入数组
          angles.push(
            this.chartConfig.circleData[i].endAngle - this.chartConfig.circleData[i].startAngle,
          );
        }	
        let angle = 0;	//定义angle,为当前模块中画到的角度
        let index = 0;	//定义index,为模块的脚标
        let start = (this.chartConfig.circleData[0].startAngle + 0.5) * 180;	//定义初始角度(0°开始)(因为this.chartConfig.circleData[i].startAngle该类型数据的范围为-0.5~2,所以转换为角度需+0.5再*180)
        let curAngle = ((speed - 3.8) / (35.2 - 3.8)) * 360;	//定义当前旋转到的角度(speed为当前动效的时间,35.2和3.8为该场景中结束和开始的时间,通过比例换算出当前角度)
        while (angle < curAngle && index < this.chartConfig.circleData.length) {	//当画到的角度小于已经转到的角度,并且没超过模块总数时,执行while循环
          if (index == 0) {	//在画第一个模块时,初始角度为0°
            start = start + 0;
          } else {	//在画除第一个模块时,初始角度为上一个初始角度+上一个模块的角度
            start = start + angles[index - 1] * 180;
          }
          let end = start + angles[index] * 180;	//定义结束角度为起始角度加上该模块的角度(*180是为了数据换算为角度)
          angle = end > curAngle ? curAngle : end;	//判断当前转到的角度是否小于该模块的结束角度,如果小于则画到当前角度,如果大于则画到结束角度(取小)
          const ring = {	//每一模块的属性
            color: this.chartConfig.circleData[index].color,
            x: this.chartConfig.centerX,
            y: this.chartConfig.centerY,
            r: this.chartConfig.radius,
            sAngle: start / 180 - 0.5,	//将开始角度换算回数据
            eAngle: angle / 180 - 0.5,	//将画到的角度换算回数据
            lineWidth: this.chartConfig.lineWidth,
            counterclockwise: this.chartConfig.counterclockwise,
          };
          this.$draw.drawSimpleRing(this.ctx, ring);	//绘制
          if (end < curAngle) {	//当前转到的角度如果比结束角度大,则让index++进入下一个模块继续绘制
            index++;
          }
        }
      }

该方法用while的方式,通过判断当前角度是否超过当前模块的结束角度来控制正在绘制的模块,只有当当前模块绘制完成时,index才++,才能进入下一个循环,继续下一模块的绘制。避免了所有模块同时绘制的情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值