Read the original article:Progress sliding rating dynamic effect implementation
Problem Description
How to customize the pattern to achieve the dynamic effect of sliding rating?
Background Knowledge
- ContentModifier supports customizing the content area of a specific component through the style builder.
- The Progress bar component is used to display the progress of content loading or operation processing.
- PanGesture sliding gesture event, which is triggered when the minimum sliding distance reaches the set minimum value.
Solution
1.Customize the scoring style.
class MyProgressModifier implements ContentModifier<ProgressConfiguration> {
// todo: Detailed attribute definition
applyContent(): WrappedBuilder<[ProgressConfiguration]> {
return wrapBuilder(myProgress);
}
}
2.Draw the left and right scoring paths respectively as the filling standard for the 0.5 score.
// todo:Path component for drawing pentagram tracks
@Builder
function leftStar(config: ProgressConfiguration, value: number) {
}
@Builder
function rightStar(config: ProgressConfiguration, value: number) {
}
3.Handle related attribute changes when the gesture slides and render the page.
Progress({ value: this.currentValue, total: 10 })
.contentModifier(this.modifier)
.gesture(
PanGesture()
// todo:Progress processing when gesture sliding
.onActionStart((event: GestureEvent) => {
})
.onActionUpdate((event: GestureEvent) => {
})
)
.margin(30)
The effect diagram is as follows:
Complete code:
class MyProgressModifier implements ContentModifier<ProgressConfiguration> {
color: Color = Color.White;
outerRadius: number = 300;
innerRadius: number;
idList: Array<string> = ['1', '3', '5', '7', '9'];
constructor(color: Color, outerRadius: number) {
this.color = color;
this.outerRadius = outerRadius;
this.innerRadius = outerRadius * sin(18) / cos(36);
}
paintingPath(startX: number, startY: number, isHalf: boolean = false, isLeft: boolean = true) {
let point1: string = `${startX} ${startY}`;
let point3: string = `${startX - this.outerRadius * cos(18)} ${startY - (sin(18) - 1) * this.outerRadius}`;
let point5: string = `${startX - this.outerRadius * cos(54)} ${startY - (-sin(54) - 1) * this.outerRadius}`;
let point7: string = `${startX + this.outerRadius * cos(54)} ${startY - (-sin(54) - 1) * this.outerRadius}`;
let point9: string = `${startX + this.outerRadius * cos(18)} ${startY - (sin(18) - 1) * this.outerRadius}`;
let point2: string =
`${startX - this.innerRadius * cos(54)} ${startY - this.innerRadius * sin(54) + this.outerRadius}`;
let point4: string =
`${startX - this.innerRadius * cos(18)} ${startY + this.innerRadius * sin(18) + this.outerRadius}`;
let point6: string = `${startX} ${startY + this.innerRadius + this.outerRadius}`;
let point8: string =
`${startX + this.innerRadius * cos(18)} ${startY + this.innerRadius * sin(18) + this.outerRadius}`;
let point10: string =
`${startX + this.innerRadius * cos(54)} ${startY - this.innerRadius * sin(54) + this.outerRadius}`;
if (!isHalf) {
return `M${point1} L${point2} L${point3} L${point4} L${point5} L${point6} L${point7} L${point8} L${point9} L${point10} L${point1} Z`
}
if (isLeft) {
return `M${point1} L${point2} L${point3} L${point4} L${point5} L${point6} `
}
return `M${point6} L${point7} L${point8} L${point9} L${point10} L${point1} `
}
applyContent(): WrappedBuilder<[ProgressConfiguration]> {
return wrapBuilder(myProgress);
}
}
@Builder
function leftStar(config: ProgressConfiguration, value: number) {
Path()
.width(20)
.height(20)
.commands((config.contentModifier as MyProgressModifier).paintingPath(35, 0, true, true))
.fill(config.enabled && config.value >= value ? (config.contentModifier as MyProgressModifier).color :
Color.White)
.stroke(Color.Black)
.strokeLineCap(LineCapStyle.Round)
.strokeLineJoin(LineJoinStyle.Round)
.strokeWidth(2)
}
@Builder
function rightStar(config: ProgressConfiguration, value: number) {
Path()
.width(20)
.height(20)
.commands((config.contentModifier as MyProgressModifier).paintingPath(0, 0, true, false))
.fill(config.enabled && config.value >= value ? (config.contentModifier as MyProgressModifier).color :
Color.White)
.stroke(Color.Black)
.strokeLineCap(LineCapStyle.Round)
.strokeLineJoin(LineJoinStyle.Round)
.strokeWidth(2)
}
@Builder
function myProgress(config: ProgressConfiguration) {
Column({ space: 30 }) {
Row() {
Flex({ justifyContent: FlexAlign.Start }) {
ForEach((config.contentModifier as MyProgressModifier).idList, (item: string) => {
leftStar(config, Number(item))
rightStar(config, Number(item) + 1)
}, (item: string) => item)
}
.width('100%')
.height(20)
}
}.margin({ bottom: 100 })
Text('Current rating:').fontSize(20)
Text(`${config.value / 2}`).fontSize(20)
}
@Entry
@Component
struct Index4 {
@State currentValue: number = 0;
modifier = new MyProgressModifier(Color.Yellow, 40);
@State myModifier: (MyProgressModifier | undefined) = this.modifier;
progressX: number = 0;
context: UIContext = this.getUIContext()
build() {
Column() {
Progress({ value: this.currentValue, total: 10 })
.contentModifier(this.modifier)
.gesture(
PanGesture()
.onActionStart((event: GestureEvent) => {
this.progressX = event.fingerList[0].localX;
this.currentValue = this.context.vp2px(this.progressX) / 100
})
.onActionUpdate((event: GestureEvent) => {
this.progressX = event.fingerList[0].localX;
this.currentValue = this.context.vp2px(this.progressX) / 100
})
)
.margin(30)
}.width('100%').height('100%')
}
}
function cos(d: number) {
return Math.cos(d * 3.14 / 180)
}
function sin(d: number) {
return Math.sin(d * 3.14 / 180)
}

Top comments (0)