HarmonyOS鸿蒙Next应用开发实战-随易App 幸运转盘页面&饼状图组件
HarmonyOS鸿蒙Next应用开发实战-随易App 幸运转盘页面&饼状图组件
介绍
在本次开发实战中,您将熟悉Canvas组件的使用,设计完成一个饼状图组件。再通过Swiper组件和ForEach循环渲染来扩展页面。最终添加动画完成“幸运转盘”功能。
通过本案例,您将熟悉Canvas、Swiper组件和ForEach列表渲染的使用,并添加简单的动画
相关技术要素
完整示例代码:
Gitee源码地址(本实战页面位于product/default/src/main/ets/pages/RollPage.ets)
本文以随易App的幸运转盘页面为例:
以下为实现过程:
- 首先要完成对目标实现的数据分析,饼状图的数据展示需要数据名、权重、背景颜色,以及饼状图自身的数据名称。考虑到后续的扩展和修改,再为其分别添加一个Index属性,因此设计如下对象数据结构用于饼状图数据:
class RollItem { //饼状图子选项类
id: string //选项ID
text: string //选项名称
weight: number //选项权重
color: string //选项背景颜色
constructor(id: string, text: string, weight: number, color: string) {
this.id = id
this.text = text;
this.weight = weight;
this.color = color;
}
}
class Roll { //饼状图类
index: string //饼状图ID
rollName: string //饼状图名称
rollItems: Array<RollItem> //饼状图子选项数组
constructor(index: string, rollName: string, rollItems: Array<RollItem>) {
this.index = index;
this.rollName = rollName;
this.rollItems = rollItems;
}
}
//并按照数据结构新建一个示例对象
const test_roll = new Roll('0', '吃什么?', [
new RollItem('0', '梅菜扣肉', 2, '#ffcba50b'),
new RollItem('1', '西湖醋鱼', 3, '#ffa87cf4'),
new RollItem('2', '西红柿炒鸡蛋', 2, '#ffe81b58'),
new RollItem('3', '海带炖肉', 3, '#ff38ed44'),
new RollItem('4', '穿过你的黑发我的手', 2, '#fff7942c'),
new RollItem('5', '蚂蚁上树', 3, '#ff68ead0'),
])
- 我们选择Canvas画布组件来完成饼状图的绘制功能,并完成对饼状图组件的封装
- 首先认识Canvas组件的基本使用方法
@Component
struct PieChart {
@Prop data: Roll //用于传入参数
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
//以上两句用于控制Canvas组件
build(){
Canvas(this.context)
.onReady(() => { //Canvas绘制语句写在此处
let ctx = this.context; //获取绑定的Canvas组件
ctx.beginPath(); //绘制语句示例
ctx.moveTo();
})
}
以上是Canvas组件的基本用法,注意该组件的特殊的方法onReady()
,在ArkUI框架下使用该函数对Canvas画布组件进行绘制控制,在获取到context之后,便可以通过语句控制与该context绑定的Canvas画布。例如:ctx.beginPath()
、ctx.moveTo()
等。
- 其次设计Canvas组件绘制预期饼状图,在设计时应考虑到以下需求:
为了饼状图组件的适用性和兼容性应该考虑到自适应宽高的问题,因此应该获取宽度根据实际宽度来绘制,可使用context.width获取到宽度。同时组件的宽高比例不应受影响,可使用aspectRatio属性来固定组件宽高比例。
为了饼状图组件的健壮性,weight权重的数据应该足够灵活,方便用户后续的数据输入,根据数据自动计算每个选项权重占总权重的比例。
考虑到数据的数量、权重比例等属性的复杂性,使用forEach函数来循环绘制小扇形以拼接的形式完成饼状图
具体代码实现:
Canvas(this.context)
.onReady(() => {
let ctx = this.context; //获取指定Canvas组件
const radius = ctx.width / 2; //获取半径(宽度)
let list: Array<RollItem> = this.data.rollItems //获取传入数据
let totalWeight = list.reduce<(acc: number, single: RollItem) => acc + single.weight, number>(acc => acc + single.weight, 0); //计算出总权重,子选项将根据与总权重的比例计算出角度。
let startAngle = -list[0].weight / totalWeight * 180 + 90; //此处角度控制开始渲染的位置,出于个人习惯我将第一个选项调整为正上方(默认角度为正右)
list.forEach(single => { //以下为循环绘制代码,其核心思想是通过绘制小扇形来拼接为圆形,通过权重/总权重*360便可以计算出合适的扇形角度。
const endAngle: number = startAngle + (single.weight / totalWeight) * 360; //计算占比角度方便绘制
const centerAngle = (startAngle + endAngle) / 2; //计算对称轴角度,以便确定绘制位置
ctx.beginPath(); //开始
ctx.moveTo(radius, radius); //中心点
ctx.arc(radius, radius, radius, startAngle * Math.PI / 180, endAngle * Math.PI / 180, false); //绘制扇形
ctx.closePath() //闭合路径区域
ctx.fillStyle = single.color; //选定背景颜色
ctx.fill(); //绘制背景颜色
ctx.fillStyle = '#FFFFFF'; //指定文字颜色
ctx.textAlign = 'center'; //指定对齐方式
ctx.save() //以下语句用于绘制扇形上的文字,该方案不适合较长文本,请根据实际需求使用或更改
ctx.translate(radius, radius)
ctx.rotate((centerAngle + 90) * Math.PI / 180)
const texts: Array<string> = single.text.split('');
const x = 0;
const y = radius * 0.1 + (radius * 0.1 / texts.length);
const lineHight = (radius - y) / (texts.length + 1)
const fontSize = lineHight
const font = fontSize.toString() + 'vp';
ctx.font = font;
for (let n: number = 0; n < texts.length; n++) {
ctx.fillText(texts[n], x, (-radius + lineHight + y / 2 + n * lineHight), fontSize);
}
ctx.restore() //文字绘制完毕
startAngle = endAngle; //每次循环完毕前刷新绘制角度
})
ctx.beginPath(); //以下语句用于绘制饼状图中央小圆,可省略
ctx.moveTo(radius, radius);
ctx.arc(radius, radius, radius/ 10, -45, 275, false);
ctx.closePath()
ctx.fillStyle = 0xf1f3f5;
ctx.fill();
})
.width('100%')
.aspectRatio(1)
//将以上代码补全进上文PieChart()组件中
以上代码已实现一个饼状图组件PieChart(),传入符合要求的数据项即可复用,开发者也可以定义更多入参来更灵活的修改组件的边框和样式。
- 为了展示更多的数据元素,使用轮播图组件和ForEach列表渲染来扩展页面
核心代码:
const rolls: Array<Roll> = [ //创建示例数据
new Roll('0', '吃什么?', [
new RollItem('0', '梅菜扣肉', 2, '#ffcba50b'),
new RollItem('1', '西湖醋鱼', 3, '#ffa87cf4'),
new RollItem('2', '西红柿炒鸡蛋', 2, '#ffe81b58'),
new RollItem('3', '海带炖肉', 3, '#ff38ed44'),
]),
new Roll('1', '随机颜色', [
new RollItem('0', '粉色', 2, '#ffff007a'),
new RollItem('1', '蓝色', 3, '#ff0cdec5'),
]),
new Roll('2', '抽奖', [
new RollItem('0', '三等奖', 4, '#ff05f80b'),
new RollItem('3', '特等奖', 1, '#ffecb609'),
new RollItem('4', '感谢参与', 4, '#499821'),
new RollItem('1', '二等奖', 3, '#ff5f16e1'),
new RollItem('2', '一等奖', 2, '#ffe81b58'),
])
]
@Component
struct PieChartsShow {
[@State](/user/State) dataList: Roll[] = rolls; //传入示例数据
[@State](/user/State) rotateAngle: number = 0 //预留角度变量
private swiperController: SwiperController = new SwiperController() //引入SwiperController
build() {
Swiper(this.swiperController) { //轮播组件,并绑定controller
ForEach(this.dataList, (item: Roll) => { //循环渲染,通过传入数据循环渲染
Row() {
PieChart({ data: item }) //调用饼状图组件
.width('100%')
}
.width('90%')
.margin('5%')
.aspectRatio(1)
.rotate({angle: this.rotateAngle})
.animation({ duration: this.duration, curve: Curve.Ease })
}, (item: Roll) => item.index)
}
.width('100%')
.aspectRatio(1)
.loop(true)
.indicatorInteractive(true)
.duration(1000)
.itemSpace(0)
}
}
为了方便用户切换,您添加按钮并调用this.swiperController.showNext()
、this.swiperController.showPrevious()
等方法来控制轮播图,也可以通过更改Swiper组件的属性更改显示效果。
- 添加动画效果
该功能实现较为简单简单,其核心为定义一个@State变量angle为旋转角度,并将该变量加入需要旋转的组件之中。其核心代码如下:
//1.定义角度变量
[@State](/user/State) rotateAngle: number = 0
//2.为需要旋转的组件添加以下属性,animation用于指定动画效果,详情请查阅官方文档
.rotate({angle: this.rotateAngle})
.animation({ duration: this.duration, curve: Curve.Ease })
//3.为指定控件绑定以下函数
.onClick(()=>{
this.rotateAngle = Math.floor(Math.random() * 360) + 1;;
})
通过以上学习,你已经完成了随易APP的幸运轮盘组件,详细代码请查看完整项目代码
更多关于HarmonyOS鸿蒙Next应用开发实战-随易App 幸运转盘页面&饼状图组件的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next应用开发中,实现幸运转盘页面和饼状图组件可以通过使用ArkUI框架中的自定义组件和动画功能来完成。首先,幸运转盘页面可以通过Canvas
组件绘制转盘,并使用Animation
组件实现旋转动画。转盘的每个扇形区域可以通过Path
对象绘制,并设置不同的颜色和文本标签。
饼状图组件可以通过Canvas
组件绘制,使用Arc
方法绘制每个扇形区域,并通过Text
组件添加标签。饼状图的数据可以通过@State
或@Prop
装饰器进行动态绑定,实现数据的实时更新。
在实现过程中,可以使用@Component
装饰器创建自定义组件,将幸运转盘和饼状图封装为可复用的组件。通过@State
和@Prop
装饰器管理组件的状态和属性,确保组件的响应式更新。
此外,可以通过Gesture
组件实现用户交互,例如点击转盘开始旋转,或点击饼状图的某个扇形区域显示详细信息。动画效果可以通过Animation
组件实现,设置旋转角度、持续时间和缓动函数,使转盘和饼状图的动画更加流畅。
总之,通过ArkUI框架提供的组件和API,可以高效地实现幸运转盘页面和饼状图组件,提升应用的用户体验。
更多关于HarmonyOS鸿蒙Next应用开发实战-随易App 幸运转盘页面&饼状图组件的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next应用开发中,实现“随易App”的幸运转盘页面和饼状图组件,可以按照以下步骤进行:
-
页面布局:使用
<div>
或<stack>
布局组件,设置转盘和饼状图的容器,确保页面结构清晰。 -
转盘动画:利用
<animation>
组件实现转盘的旋转效果,通过rotate
属性控制旋转角度和速度,结合onClick
事件触发旋转。 -
饼状图绘制:使用
<canvas>
组件绘制饼状图,通过arc
方法绘制扇形,结合fill
方法填充颜色,动态更新数据展示。 -
数据绑定:通过
@State
和@Prop
实现数据与UI的绑定,确保转盘和饼状图的数据同步更新。 -
交互优化:添加触摸事件和动画过渡效果,提升用户体验,确保页面流畅性和响应速度。
通过这些步骤,可以高效实现幸运转盘页面和饼状图组件,提升应用的用户体验。