系列文章目录
HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉浸式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)
HarmonyOS Next系列之地图组件(Map Kit)使用(九)
HarmonyOS Next系列之半圆环进度条实现(十)
前言
HarmonyOS Next(基于API12)实现封装一个半圆环进度条,可复用好扩展,常用于项目内仪表盘显示。
一、实现原理解析
1、通过Gauge组件绘制静态圆环形图表
2、父元素高度设置为子元素Gauge半径,并设置clip(true)进行裁剪使得组件高度刚好为半圆。
3、设置2种进度条填充颜色,根据当前进度值动态设置2种颜色占比
4、面板数据布局设计和显示
二、Gauge组件使用回顾
Gauge为数据量规图表组件,用于将数据展示为环形图表。
常用参数:
value:量规图的当前数据值,即图中指针指向位置
max:当前数据段最大值,默认值:100
min:当前数据段最小值,默认值:0
常用属性:
startAngle:设置起始角度位置,时钟0点为0度,顺时针方向为正角度,默认值:0
endAngle:设置终止角度位置,默认值:360
colors:设置量规图的颜色,类型:ResourceColor | LinearGradient | Array<[ResourceColor | LinearGradient | number]>),当设置为颜色数组时将分段显示,[color,rate]第一个参数颜色值,第二个参数占比。
例如:[[Color.white, 0.3], [Color.Black,0.7]]表示白色占进度条3/10,黑色占7/10
strokeWidth:环形宽度
indicator:指针样式,设置null不显示
trackShadow:阴影样式,设置null不显示
description:设置底部说明内容,设置null不显示
尾随闭包为中间区域内容
示例:
@Entry
@Component
struct Index {
build() {
Gauge({ value: 80, min: 1, max: 100 }) {
//中间区域内容
Text('50').fontColor('#000').fontSize(50).textAlign(TextAlign.Center)
}.strokeWidth(10)
.colors([[Color.Red, 0.3], [Color.Green, 0.7]])
}
}
三、半圆环进度条代码实现
封装一个可复用好扩展的组件:
CircularProgressBar.ets
@Component
export default struct CircularProgressBar {
@Prop title: string = '当前值' //中间标题
@Prop radius: number = 150 //半环形进度条半径
@Prop strokeWidth:number=10 //半环形进度条宽度
@Prop @Watch('valueChange') currentValue: number = 0 //当前值
@Prop maxValue: number = 100 //最大值
@Prop color: ResourceColor = '#393D49' //总进度颜色
@Prop activeColor: ResourceColor = '#28B2E3' //当前进度颜色
@Prop showPercentage: boolean = true //是否显示百分比
@State colors: [ResourceColor | LinearGradient, number][] = [] //组件进度条颜色配置
@Builder
builder() {
};
@BuilderParam builderParam: () => void = this.builder //插槽
aboutToAppear(): void {
this.valueChange()
}
//计算当前值占总的百分比
getPercentage(): number {
return Math.min(this.currentValue / this.maxValue, 1)
}
//百分比带%
getPercentageTxt(): string {
return Math.round(this.getPercentage() * 100).toString() + '%'
}
//设置进度条颜色
setColors(percentage: number) {
this.colors = [[this.activeColor, percentage], [this.color, 1 - percentage]]
}
//当前值改变监听
valueChange() {
this.setColors(this.getPercentage())
}
build() {
Column() {
Stack({ alignContent: Alignment.TopStart }) {
//环形进度条
Gauge({ value: this.currentValue, max: this.maxValue }) {
if (this.builderParam === this.builder) { //环形内部默认样式
Column() {
Text(this.title).fontSize(14).lineHeight(25).fontColor('#FFF')
Text(this.currentValue.toString())
.fontSize(70)
.fontColor('#FFF')
.fontWeight(700)
.margin({ top: '5%' })
}.height('100%').width('100%').padding({ top: '12%' })
} else { //插槽自定义样式
Column() {
this.builderParam()
}.height('100%').width('100%')
}
}
.startAngle(270)
.endAngle(90)
.strokeWidth(this.strokeWidth)
.indicator(null)
.colors(this.colors)
.width('100%')
.height(this.radius * 2)
.trackShadow(null)
.description(null)
}.height(this.radius).width('100%').clip(true)
//右侧百分比
if (this.showPercentage) {
Text(this.getPercentageTxt())
.fontSize(15)
.fontColor('#FFF')
.width('100%')
.textAlign(TextAlign.End)
.margin({ top: 8 })
.offset({ x: 8 })
}
}.width(this.radius * 2).backgroundColor('#323341')
}
}
说明:
示例代码定义了半径、环形宽度、总进度条颜色、当前进度颜色、当前值、最大值、中间区域标题等组件参数方便使用时自定义。而且定义了builderParam参数可通过尾随闭包进行中间区域内容覆盖绘制,如果不传中间区域有默认样式。
Gauge父元素Stack设置为其高度一半并进行裁剪使得底部半圆区域被裁剪掉,角度设置从270到90跨度180度半圆区域,右下角进度百分比文字单独布局。
页面调用:
import CircularProgressBar from '../components/CircularProgressBar'
@Entry
@Component
struct Index {
@State value: number = 0
aboutToAppear(): void {
//定时器模拟数据变化
let interval = setInterval(() => {
this.value++
if (this.value === 100) {
clearInterval(interval)
}
}, 300)
}
//百分比文字
getPercentageTxt() {
return `${Math.round(Math.min(this.value / 100, 1) * 100)}`
}
build() {
Column({ space: 20 }) {
//默认样式
CircularProgressBar({ title: '当前里程(km)', currentValue: this.value })
//自定义样式1
CircularProgressBar({ radius: 100, currentValue: this.value, activeColor: '#2EB977' }) {
Column() {
Text('剩余里程(km)').fontSize(12).fontColor('#FFF')
Text((100 - this.value).toString())
.fontSize(45)
.fontColor('#FFF')
.fontWeight(700)
.margin({ top: 8 })
}.margin({ top: '18%' })
}
//自定义样式2
CircularProgressBar({
radius: 120,
currentValue: this.value,
activeColor: '#FAA10F',
showPercentage: false
}) {
Column() {
Flex({ alignItems: ItemAlign.Baseline, justifyContent: FlexAlign.Center }) {
Text(this.getPercentageTxt()).fontColor('#fff').fontSize(55)
Text('%').fontSize(15).fontColor('#fff').margin({ left: 2 })
}
Text(`已行驶${this.value}km`).fontSize(12).fontColor('#fff').margin({ top: 8 })
}.margin({ top: '15%' })
}
}.backgroundColor('#323341').width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
运行效果: