Read the original article:How to Implement a Digital Display Component with Scroll Animation Effects
How to Implement a Digital Display Component with Scroll Animation Effects
Problem Description
How to implement a numeric display component with a scrolling animation effect, where the number can be increased by clicking a button, and the number will transition to the new value with an animation effect.
Background Knowledge
- The explicit animation interface animateTo can specify the insertion of transition effects for state changes caused by closure code.
- The general property translate can set the component's translation, allowing the component to move within a coordinate system where the top-left corner of the component serves as the origin. The margin property can set the margin properties of the component, maintaining its relative position.
Solution
1.Define state variables. The state variable scrollNumber is bound to the num state of the parent component using the @Prop and @Watch decorators. When the num value changes, the changeNumber method is called. Other state variables are as follows:
@Prop @Watch('changeNumber') scrollNumber: number = 0;
@State bottomNum: number = 0;
@State showNumber: string = '0';
@State cacheNumber: string = '';
changeNumberFinal: string = '';
isScrolling: boolean = false;
isInit: boolean = false;
changeNumber() {
if (this.isInit) {
this.animateToScroll(this.scrollNumber);
}
}
2.Define the method initAnimateToScroll to initialize the animation and set a timer to start the animation after 50 milliseconds. In the animateToScroll method, execute the scrolling animation, update bottomNum and isScrolling based on the passed newNum, and update showNumber and cachNumber after the animation completes.
initAnimateToScroll() {
setTimeout(() => {
this.getUIContext().animateTo({
duration: 600,
onFinish: () => {
this.isInit = true;
}
}, () => {
this.bottomNum = -50;
});
}, 50);
}
animateToScroll(newNum: number) {
this.changeNumberFinal = String(newNum);
if (this.isScrolling) {
return;
}
this.cacheNumber = this.changeNumberFinal;
this.getUIContext().animateTo({
duration: 600,
onFinish: () => {
this.bottomNum = -50;
this.showNumber = this.cacheNumber;
this.cacheNumber = '';
this.isScrolling = false;
if (this.changeNumberFinal !== this.showNumber) {
this.animateToScroll(Number(this.changeNumberFinal));
}
}
}, () => {
this.bottomNum = 0;
this.isScrolling = true;
});
}
3.Control the vertical position of the numbers using the translate and margin properties, and achieve a scrolling effect in conjunction with animations.
Row() {
Text(this.showNumber)
.fontSize(35)
.fontColor('#0A59F7');
}
.margin({ bottom: this.bottomNum })
.height(50)
.translate({ y: this.bottomNum });
Complete examples are as follows:
@Entry
@Component
struct ScrollNum {
@State num: number = 0;
@State isEnabled: boolean = true;
build() {
Column({ space: 50 }) {
ScrollNumComponent({ scrollNumber: this.num });
Button('Click to add')
.enabled(this.isEnabled)
.onClick(() => {
this.isEnabled = !this.isEnabled;
setTimeout(() => {
this.num += 50;
this.isEnabled = !this.isEnabled;
}, 600);
});
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%');
}
}
@Component
export struct ScrollNumComponent {
@Prop @Watch('changeNumber') scrollNumber: number = 0;
@State bottomNum: number = 0;
@State showNumber: string = '0';
@State cacheNumber: string = '';
changeNumberFinal: string = '';
isScrolling: boolean = false;
isInit: boolean = false;
changeNumber() {
if (this.isInit) {
this.animateToScroll(this.scrollNumber);
}
}
aboutToAppear(): void {
this.initAnimateToScroll();
}
initAnimateToScroll() {
setTimeout(() => {
this.getUIContext().animateTo({
duration: 600,
onFinish: () => {
this.isInit = true;
}
}, () => {
this.bottomNum = -50;
});
}, 50);
}
animateToScroll(newNum: number) {
this.changeNumberFinal = String(newNum);
if (this.isScrolling) {
return;
}
this.cacheNumber = this.changeNumberFinal;
this.getUIContext().animateTo({
duration: 600,
onFinish: () => {
this.bottomNum = -50;
this.showNumber = this.cacheNumber;
this.cacheNumber = '';
this.isScrolling = false;
if (this.changeNumberFinal !== this.showNumber) {
this.animateToScroll(Number(this.changeNumberFinal));
}
}
}, () => {
this.bottomNum = 0;
this.isScrolling = true;
});
}
build() {
Column() {
Row() {
Text(this.cacheNumber)
.fontSize(35)
.fontColor('#0A59F7');
}
.height(50)
.translate({ y: this.bottomNum });
Row() {
Text(this.showNumber)
.fontSize(35)
.fontColor('#0A59F7');
}
.margin({ bottom: this.bottomNum })
.height(50)
.translate({ y: this.bottomNum });
}
.clip(true)
.height(50);
}
}

Top comments (0)