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

本文主要通过抽奖转盘小项目讲解在鸿蒙开发中如何使用画布组件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学习资料免费领取(安全链接,放心点击

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/682666.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

运维系列.Linux下的用户管理

运维系列 Linux下的用户管理 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/ar…

[RK3588-Android12] 关于BQ25703充电IC+CW2017电量计调试

问题描述 BQ25703充电ICCW2017电量计调试 解决方案&#xff1a; 附上dts配置文件 &i2c6 {clock-frequency <400000>;status "okay";// CONFIG_BATTERY_CW2017cw2017: cw201763 {status "okay";compatible "cellwise,cw2017";re…

数字影像产业园的三大赋能:科技、创新与无限可能

数字影像产业园作为文创产业的重要载体&#xff0c;以科技为核心驱动力&#xff0c;不断推动产业的技术革新和升级。 园区内汇聚了最前沿的数字技术资源&#xff0c;高清摄影设备、虚拟现实技术、人工智能应用等尖端科技在这里得到广泛应用&#xff0c;不仅提升了生产效率&…

如何一键批量下载淘宝高清主图、详情图、sku及视频信息

图片对电商至关重要&#xff0c;因为它们是商品展示的主要方式&#xff0c;直接影响消费者的购买决策。高质量的图片能够吸引顾客注意&#xff0c;提升产品吸引力&#xff0c;增加点击率和转化率。此外&#xff0c;好的图片还有助于建立品牌形象&#xff0c;提高客户信任度。 …

算法金 | 10 大必知的自动化机器学习库(Python)

大侠幸会&#xff0c;在下全网同名[算法金] 0 基础转 AI 上岸&#xff0c;多个算法赛 Top [日更万日&#xff0c;让更多人享受智能乐趣] 一、入门级自动化机器学习库 1.1 Auto-Sklearn 简介&#xff1a; Auto-Sklearn 是一个自动机器学习库&#xff0c;基于 Python 的 scikit…

IP黑名单与IP白名单是什么?

在IP代理使用中&#xff0c;我们经常听到黑名单与白名单两个名词&#xff0c;它们不仅提供了强大的防御机制&#xff0c;还可以灵活应对不同的安全威胁。本文将详细探讨IP黑名单和白名单在网络安全中的双重屏障作用。 一、IP黑名单和白名单定义 IP黑名单与IP白名单是网络安全中…

AI技能培训课程知识付费小程序的作用是什么

AI近些年逐渐走入工作生活中&#xff0c;如AI创作/绘图/视频/配音/渲染等&#xff0c;妙用AI可以节约大量时间和带来灵感&#xff0c;不少平台或个人也在围绕其开展生意&#xff0c;技术在不断进步&#xff0c;对此感兴趣及想要应用的用户/单位也不少&#xff0c;但苦于不掌握不…

linux信号集与信号掩码-保护信号处理程序,确保进程正确运行

在Linux环境下&#xff0c;当进程收到信号时&#xff0c;如何优雅地处理并确保程序的正常运行?这就需要借助信号集和信号掩码的功能。本文将为你揭开信号集和信号掩码的神秘面纱&#xff0c;并通过生动的代码示例&#xff0c;让你彻底掌握在C程序中使用它们的技巧。 一、信号集…

【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【06】【商品服务】接口文档地址_三级分类_SPU_SKU

持续学习&持续更新中… 学习态度&#xff1a;守破离 【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【06】【商品服务】接口文档地址_三级分类_SPU_SKU 接口文档地址三级分类效果图建表后台组建数据的树形结构在人人(后台管理系统)中实现管理商品的三级分类路径规则使用…

开关电源基本原理1

目录 内容概述 关于电感 认识电感 电感充电 电感储能 电感充电 电感参数 电感放电 利用电感升压 电感电流波形 伏秒法则 电流纹波率 电感电流三种导电模式 电流纹波率与频率的关系 电流纹波率与电感值的关系 电感值与电感体积 电路纹波率r的最优值 电感值与电…

出行预测:端午打车需求将上涨31%,滴滴发放超2亿司机补贴

作为上半年的“收官”小长假&#xff0c;端午假期接棒“五一”的出行热度&#xff0c;中短途周边游持续升温&#xff0c;海滨旅行、龙舟民俗体验成为新的出行看点。 滴滴出行预测&#xff0c;端午节当天&#xff08;6月10日&#xff09;打车需求将同比去年上涨约31%。今年端午…

[数据集][图像分类]十二生肖分类数据集8492张12类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;8492 分类类别数&#xff1a;12 类别名称:["dog","dragon&q…

【RISC-V】站在巨人的肩膀上——看开源芯片、软件生态、与先进计算/人工智能/安全的结合

目录 会议议程专题二&#xff1a;RISC-V与先进计算基于RISC-V的后量子密码芯片设计&#xff0c;刘冬生&#xff0c;华中科技大学存算一体集成芯片&#xff0c;刘琦&#xff0c;复旦大学面向端侧大模型计算的RISC-V矩阵扩展架构&#xff0c;复旦大学&#xff0c;韩 军 专题五&am…

电子电气架构 —— 刷写模式:并行刷写

电子电气架构 —— 刷写模式:并行刷写 我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人们会在生活中不断攻击你。他们的主要武器是向你灌输对自己的怀疑:你的价值、你的能力、你的潜力。他们往往会将此…

云原生架构案例分析_5.某体育用品公司云原生架构的业务中台构建

1.背景和挑战 某体育用品公司作为中国领先的体育用品企业之一&#xff0c;在2016年&#xff0c;某体育用品公司启动集团第三次战略升级&#xff0c;打造以消费者体验为核心的“3”&#xff08;“互联网”、“体育”和“产品”&#xff09;的战略目标&#xff0c;积极拥抱云计算…

基于GFlowNets的蚁群抽样组合优化

本文将基于GFACS论文&#xff0c;探讨其核心思想、技术细节以及在实际应用中的优势。 GFlowNet&#xff1a;摊销MCMC成本的有效工具 GFACS的核心是GFlowNet&#xff0c;它通过训练学习状态转移的概率分布&#xff0c;从而替代传统的MCMC采样方法。GFlowNet的优势在于&#xff1…

Java——循环语句

下面我们介绍循环控制结构。如果您想要同样的操作执行多次&#xff0c;就需要使用循环结构。Java中有三种主要的循环结构&#xff1a; for 循环while 循环do…while 循环 一、for 循环 for循环是一种控制结构&#xff0c;用于反复执行一段代码&#xff0c;直到满足指定的条件…

每天五分钟深度学习PyTorch:Tensor张量的索引和切片

本文重点 有时候当我们拥有一个Tensor张量的时候,我们可能需要获取它某一维度的信息,那么此时我们就需要索引和切片的技术,它们可以帮助我们解决这些问题。 切片操作 a是四维的,然后默认是从第一维开始取,逗号表示取不同的维度 a[:2]表示第一维取0,1,后面三维取所有 …

JAVA小案例-分别计算100以内奇数和偶数的和

JAVA小案例-分别计算100以内奇数和偶数的和 没啥可说的&#xff0c;就是for循环加if分支&#xff0c;也可以用while写。 代码如下&#xff1a; public class Jiouhe {/*** 分别计算100以内奇数和偶数的和* param args*/public static void main(String[] args){int sum10;in…

C语言数据结构快速排序的非递归、归并排序、归并排序的非递归等的介绍

文章目录 前言一、快速排序非递归二、归并排序五、归并排序非递归总结 前言 C语言数据结构快速排序的非递归、归并排序、归并排序的非递归等的介绍 一、快速排序非递归 快速排序非递归的定义 快速排序非递归&#xff0c;需要使用栈来实现。将左右下标分别push到栈中。在栈为…