介绍
本篇Codelab是基于画布组件、显式动画,实现的一个自定义抽奖圆形转盘。包含如下功能:
- 通过画布组件Canvas,画出抽奖圆形转盘。
- 通过显式动画启动抽奖功能。
- 通过自定义弹窗弹出抽中的奖品。
相关概念
- Stack组件:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
- Canvas:画布组件,用于自定义绘制图形。
- CanvasRenderingContext2D对象:使用RenderingContext在Canvas组件上进行绘制,绘制对象可以是矩形、文本、图片等。
- 显式动画:提供全局animateTo显式动画接口来指定由于闭包代码导致的状态变化插入过渡动效。
- 自定义弹窗: 通过CustomDialogController类显示自定义弹窗。
源码下载
环境搭建
硬件要求
- DevEco Studio版本:DevEco Studio NEXT Developer Beta1及以上。
- HarmonyOS SDK版本:HarmonyOS NEXT Developer Beta1 SDK及以上。
环境搭配
- 安装DevEco Studio,详情请参考下载和安装软件。
- 设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,详情请参考配置开发环境。
代码结构解读
├──entry/src/main/ets // 代码区
│ ├──common
│ │ ├──constants
│ │ │ ├──ColorConstants.ets // 颜色常量类
│ │ │ ├──CommonConstants.ets // 公共常量类
│ │ │ └──StyleConstants.ets // 样式常量类
│ │ └──utils
│ │ ├──CheckEmptyUtils.ets // 数据判空工具类
│ │ └──Logger.ets // 日志打印类
│ ├──entryability
│ │ └──EntryAbility.ts // 程序入口类
│ ├──pages
│ │ └──CanvasPage.ets // 主界面
│ ├──view
│ │ └──PrizeDialog.ets // 中奖信息弹窗类
│ └──viewmodel
│ ├──DrawModel.ets // 画布相关方法类
│ ├──FillArcData.ets // 绘制圆弧数据实体类
│ └──PrizeData.ets // 中奖信息实体类
└──entry/src/main/resources // 资源文件目录
构建主界面
在绘制抽奖圆形转盘前,首先需要在CanvasPage.ets的aboutToAppear方法中获取屏幕的宽高。在CanvasPage.ets布局界面中添加Canvas组件,在onReady方法中进行绘制。 在DrawModel.ets中,通过draw方法逐步进行自定义圆形抽奖转盘的绘制。
画外部圆盘
画外部圆盘的花瓣:通过调用rotate()方法,将画布旋转指定角度。再通过调用save()和restore()方法,使画布保存最新的绘制状态。根据想要绘制的花瓣个数,改变旋转角度,循环画出花瓣效果。
画外部圆盘、圆盘边上的小圈圈:在指定的X、Y(0, 0)坐标处,画一个半径为this.screenWidth * CommonConstants.OUT_CIRCLE_RATIOS的圆形。接下来通过一个for循环,且角度每次递增CommonConstants.CIRCLE / CommonConstants.SMALL_CIRCLE_COUNT,来绘制圆环上的小圈圈。
画内部扇形抽奖区域
画内部圆盘、内部扇形抽奖区域:使用fillArc方法绘制内部圆盘。通过一个for循环,角度每次递增this.avgAngle。然后不断更改弧线的起始弧度this.startAngle * Math.PI / CommonConstants.HALF_CIRCLE和弧线的终止弧度(this.startAngle + this.avgAngle) * Math.PI / CommonConstants.HALF_CIRCLE。最后用fill()方法对路径进行填充。
画内部抽奖区域文字:用for循环,通过drawCircularText()方法绘制每组文字。drawCircularText()方法接收三个参数,分别是字符串,起始弧度和终止弧度。绘制文本前需要设置每个字母占的弧度angleDecrement,然后设置水平和垂直的偏移量。垂直偏移量circleText.y - Math.sin(angle) * radius就是朝着圆心移动的距离;水平偏移circleText.x + Math.cos(angle) * radius,是为了让文字在当前弧范围文字居中。最后使用fillText方法绘制文本。
画内部抽奖区域文字对应图片:使用drawImage方法绘制抽奖区域文字对应图片,该方法接收该方法接收五个参数,分别是图片资源、绘制区域左上角的X和Y轴坐标、绘制区域的宽度和高度。
实现抽奖功能
在CanvasPage.ets的Canvas组件中添加rotate属性,在Image组件中添加点击事件onClick。点击“开始抽奖”图片,圆形转盘开始转动抽奖。
圆形转盘开始转动抽奖:给转盘指定一个随机的转动角度randomAngle,保证每次转动的角度是随机的,即每次抽到的奖品也是随机的。动画结束后,转盘停止转动,抽奖结束,弹出抽中的奖品信息。
弹出抽中的奖品信息:抽奖结束后,弹出抽中的文本和图片信息,通过自定义弹窗实现。