Read the original article:Synchronizing Multiple Text Marquee Animations
Context
When implementing a text marquee card feature in HarmonyOS applications, developers need to create a coordinated animation system where multiple text elements scroll horizontally. The challenge lies in ensuring that when one text element reaches the boundary of its container, it pauses and waits for all other text animations to complete before resetting. This synchronization is essential for creating a polished, professional user experience where all carousel elements remain coordinated throughout their animation cycles.
Description
The issue involves implementing a text carousel feature with the following requirements:
- Multiple text strings need to scroll horizontally within fixed-width containers
- Each text element scrolls at its own pace based on its length
- When a text element reaches the end of its scrollable area, it must pause
- The animation should only reset to the beginning when ALL text elements have completed their scrolling
- The entire process should repeat automatically in a synchronized manner
The HarmonyOS framework provides two key components for this functionality:
- Scroll: A scrollable container component that allows content to scroll when child components exceed the parent component's dimensions
-
Scroller: A controller for scrollable container components that can be bound to a Scroll component to programmatically control scrolling behavior, including methods like
isAtEnd()to detect scroll position
Solution
The solution uses Scroller to control Scroll component animations with timer-based automatic scrolling. The isAtEnd() method monitors scroll state to determine when text has completely displayed, ensuring coordinated animation control.
Entry Component:
@Entry
@Component
struct Index {
@State textList: string[] = [
'this is a test string1 this is a test string1 this is a test string1.',
'this is a test string2 this is a test string2.',
'this is a test string3 this is a test string3 this is a test string3 this is a test string3.', ]
build() {
Row() {
Column() {
myMarqueeCard({
textList: this.textList,
})
}
.width('100%')
}
.height('100%')
}
}
Custom Marquee Card Component:
@Component
struct myMarqueeCard {
@Prop textList: string[]
scroller1: Scroller = new Scroller()
scroller2: Scroller = new Scroller()
scroller3: Scroller = new Scroller()
build() {
Column() {
this.SingleText(this.textList[0], this.scroller1)
this.SingleText(this.textList[1], this.scroller2)
this.SingleText(this.textList[2], this.scroller3)
}
}
@Builder
SingleText(text: string, scroller: Scroller) {
Scroll(scroller) {
Row() {
Text(text).fontSize(30)
}
}
.width(300)
.scrollable(ScrollDirection.Horizontal)
.enableScrollInteraction(false)
.scrollBar(BarState.Off)
.onAppear(() => {
this.handleScroll(scroller)
})
}
handleScroll(scroller: Scroller) {
let timer: number = setInterval(() => {
const curOffset: OffsetResult = scroller.currentOffset()
scroller.scrollTo({
xOffset: curOffset.xOffset + 50, yOffset: curOffset.yOffset, animation: {
duration: 1000,
curve: Curve.Linear
}
})
if (scroller.isAtEnd()) {
clearInterval(timer);
if (this.scroller1.isAtEnd() && this.scroller2.isAtEnd() && this.scroller3.isAtEnd()) {
this.scroller1.scrollTo({xOffset: 0, yOffset: 0, animation: { duration: 0 }})
this.scroller2.scrollTo({xOffset: 0, yOffset: 0, animation: { duration: 0 }})
this.scroller3.scrollTo({xOffset: 0, yOffset: 0, animation: { duration: 0 }})
}
}
}, 500)
}
}
Implementation Details:
-
Create Multiple Scroller Instances: Each text element gets its own
Scrollercontroller for independent control -
Implement Automatic Scrolling: Use
setIntervalto increment scroll offset by 50 pixels every 500ms with 1000ms animation duration -
Monitor Scroll State: Utilize the
isAtEnd()method to detect when each text element reaches the end - Synchronize Reset: Check if all scrollers have reached the end before resetting all animations simultaneously to position 0 with zero animation duration
Key Takeaways
- Use
Scrollercontrollers with timer-based offset increments to create custom marquee animations in HarmonyOS - The
isAtEnd()method is essential for detecting scroll completion and coordinating multiple animations - Disable scroll interaction (
enableScrollInteraction(false)) to prevent manual scrolling interference with animations - Synchronize multiple scrollers by checking all their states before performing collective actions like resets
- Set animation duration to 0 when resetting scroll positions to create seamless loop transitions
- Each text element can scroll at different speeds naturally based on content length, but all pause and reset together for coordinated behavior
Top comments (0)