纯血鸿蒙开发实战—如何使用画布组件Canvas绘制图形和文字,以及转圈动画的实现

164 篇文章 1 订阅
154 篇文章 1 订阅

本文主要通过抽奖转盘小项目讲解在鸿蒙开发中如何使用画布组件Canvas绘制图形和文字,以及转圈动画的实现。效果图如下:

首先绘制转盘的六个分区:

drawInnerArc() {
    let colors = [
      'rgb(61,127,255)','rgb(121,189,255)'
    ];
    let radius = this.screenWidth * 0.336;
    for (let i = 0; i < 6; i++) {
      if (this.canvasContext !== undefined) {
        this.canvasContext.beginPath();
        this.canvasContext.fillStyle = colors[i%2];
        this.canvasContext.arc(0, 0, radius,
          this.startAngle * Math.PI / 180,  (this.startAngle + this.avgAngle) * Math.PI / 180);
        this.canvasContext.fill();
      }
      this.canvasContext?.lineTo(0, 0);
      this.canvasContext?.fill();
      this.startAngle += this.avgAngle;
    }
  }

在界面中添加画布组件,将转盘区域绘制出来:


Canvas(this.canvasContext)
        .width('100%')
        .height('100%')
        .onReady(() => {
          this.drawModel.draw(this.canvasContext, this.screenWidth, this.screenHeight);
        })

然后在转盘的分区上分别绘制文字,注意,这里的文字使用Text组件并不容易实现,因为要进行角度的调整,使每个文字都朝向圆心的位置:

let textArrays = [
      "玉米","番茄","西瓜","苹果","樱桃","菠萝"
    ];

    let arcTextStartAngle = 34;
    let arcTextEndAngle = 26;
    for (let i = 0; i < 6; i++) {
      
      let startAngle = (this.startAngle + arcTextStartAngle) * Math.PI / 180
      let endAngle = (this.startAngle + arcTextEndAngle) * Math.PI / 180

      class CircleText {
        x: number = 0;
        y: number = 0;
        radius: number = 0;
      }
      let circleText: CircleText = {
        x: 0,
        y: 0,
        radius: this.screenWidth * 0.336
      };
      // The radius of the circle.
      let radius = circleText.radius - circleText.radius / 6;
      // The radians occupied by each letter.
      let angleDecrement = (startAngle - endAngle) / (textArrays[i].length - 1);
      let angle = startAngle;
      let index = 0;
      let character: string;

      while (index < textArrays[i].length) {
        character = textArrays[i].charAt(index);
        this.canvasContext?.save();
        this.canvasContext?.beginPath();
        this.canvasContext?.translate(circleText.x + Math.cos(angle) * radius,
          circleText.y - Math.sin(angle) * radius);
        this.canvasContext?.rotate(Math.PI / 2 - angle);
        this.canvasContext?.fillText(character, 0, 0);
        angle -= angleDecrement;
        index++;
        this.canvasContext?.restore();
      }
      
      this.startAngle += this.avgAngle;
    }

此时一个基本的转盘已经完成了,可以在转盘外增加一个大转盘作为修饰:


drawOutCircle() {
    // Draw outer disc.
    this.fillArc(new FillArcData(0, 0, this.screenWidth * 0.4, 0,
      Math.PI * 2),  'rgb(102,177,255)');

    let beginAngle = this.startAngle;
    // Draw small circle.
    for (let i = 0; i < 8; i++) {
      this.canvasContext?.save();
      this.canvasContext?.rotate(beginAngle * Math.PI / 180);
      
      if (this.canvasContext !== undefined) {
        this.canvasContext.beginPath();
        this.canvasContext.fillStyle = '#FFFFFF';
        this.canvasContext.arc(this.screenWidth * 0.378, 0, 4.1,
          0, 360);
        this.canvasContext.fill();
      }
      
      beginAngle = beginAngle + 360 / 8;
      this.canvasContext?.restore();
    }
  }

使用叠加布局为转盘添加指针:

Stack({ alignContent: Alignment.Center }) {
      Canvas(this.canvasContext)
        .width('100%')
        .height('100%')
        .onReady(() => {
          this.drawModel.draw(this.canvasContext, this.screenWidth, this.screenHeight);
        })
        .rotate({
          x: 0,
          y: 0,
          z: 1,
          angle: this.rotateDegree,
          centerX: this.screenWidth / 2,
          centerY: this.screenHeight / 2
        })

      Image($r('app.media.btn_start'))
        .width('19.3%')
        .height('10.6%')
        .enabled(this.enableFlag)
       
    }

好了,界面大功告成。接下来是动画部分,我们可以给指针添加一个点击事件,为转盘添加旋转动画:


startAnimator() {
    let randomAngle = Math.round(Math.random() * 360);

    animateTo({
      duration: 4000,
      curve: Curve.Ease,
      delay: 0,
      iterations: 1,
      playMode: PlayMode.Normal,
      onFinish: () => {
        this.rotateDegree = 270 - randomAngle;
      }
    }, () => {
      this.rotateDegree = 360 * 5 +
      270 - randomAngle;
    })
  }
Image($r('app.media.btn_start'))
        .width('19.3%')
        .height('10.6%')
        .enabled(this.enableFlag)
        .onClick(() => {
          this.enableFlag = !this.enableFlag;
          this.startAnimator();
        })

最后

如果你想快速提升鸿蒙技术,那么可以直接领取这份包含了:【OpenHarmony多媒体技术、Stage模型、ArkUI多端部署、分布式应用开发、音频、视频、WebGL、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。

鸿蒙Next全套VIP学习资料←点击领取!(安全链接,放心点击

1.鸿蒙核心技术学习路线

2.大厂面试必问面试题

3.鸿蒙南向开发技术

 4.鸿蒙APP开发必备

 5.HarmonyOS Next 最新全套视频教程

 6.鸿蒙生态应用开发白皮书V2.0PDF

这份全套完整版的学习资料已经全部打包好,朋友们如果需要可以点击鸿蒙Next全套VIP学习资料免费领取(安全链接,放心点击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值