Skip to content

Transition 过渡 ​

Vue 风格的 <Transition>、按 key 切换的视图切换器与 <TransitionGroup>,基于 ArkUI 组件转场(TransitionEffect.asymmetric + if / ForEach 的 key)。时序来自 SparkAnim:--motion-transition-* 可配置,关闭动效后所有切换立即完成。

过渡完全是动画效果,网页预览无法还原,本页示例只展示代码。请在 HarmonyOS 设备或画廊应用中查看实际效果。

显示 / 隐藏 ​

STransition 根据 show(相当于 v-if)挂载与移除内容。生命周期事件:onBeforeEnter、onAfterEnter、onBeforeLeave、onAfterLeave。

arkts
@Local open: boolean = true;

SButton({ text: 'Toggle' }).onClick(() => this.open = !this.open)
STransition({ show: this.open, name: 'slide-down', distance: '24vp',
  onAfterEnter: () => { ... }, onAfterLeave: () => { ... } }) {
  DemoPane({ title: 'Hello', body: '...' })
}

切换过渡 ​

SSwitchTransition 渲染 pageBuilder(current),并在新旧视图之间做动画;只有在过渡进行时两者才同时挂载。mode 为 'out-in' / 'in-out' 时依次执行,'default' 同时执行。切换到 order 中更靠前的 key 时,带方向的预设会反向。

arkts
@Local view: string = 'inbox';

@LocalBuilder
renderView(key: string) {
  // build from the key argument, so the leaving view keeps its own content
  DemoPane({ title: key, body: '...' })
}

SSwitchTransition({
  current: this.view,
  pageBuilder: this.renderView,
  name: 'shared-axis-x',      // fade | slide-* | scale | zoom | fade-through | shared-axis-x/y/z | none
  mode: 'out-in',             // 'default' (simultaneous) | 'out-in' | 'in-out'
  order: ['inbox', 'drafts', 'sent'],   // navDirection 'auto': later key = forward
  onBeforeLeave: (k: string) => { ... },
  onAfterEnter: (k: string) => { ... }
})

页面过渡 ​

SPageTransition 是页面级的切换器(RouterView + Transition):默认是 X 轴共享轴动画,方向取自 index、order 或访问历史。用同样的方式包裹画廊的 DocContent,即可在文档页面之间切换时产生动画。

arkts
// Vue: <RouterView v-slot="{ Component }"><Transition name="slide-left">…
@Local step: number = 0;

@LocalBuilder
renderStep(key: string) { DemoPane({ title: key }) }

SPageTransition({
  current: STEPS[this.step],
  index: this.step,          // or order: STEPS, or neither (visit history: going back = back)
  pageBuilder: this.renderStep,
  name: 'slide-left'         // default 'shared-axis-x'
})
SButton({ text: 'Back' }).onClick(() => this.step--)   // reverses the slide
SButton({ text: 'Next' }).onClick(() => this.step++)

// gallery shell (pages/Index.ets): animate between doc pages
@LocalBuilder renderPage(key: string) { DocContent({ page: key }) }
SPageTransition({ current: this.page, pageBuilder: this.renderPage, order: NAV_ORDER, name: 'fade-through' })

自定义效果与时序 ​

enterEffect / leaveEffect 接受任意 TransitionEffect(继承解析出的时长与曲线);duration 与 ease 可按实例覆盖动效 key。

arkts
STransition({
  show: this.open,
  duration: 600,                      // per-instance override (ms); motion off still wins
  ease: 'spring(0.5, 0.7)',
  enterEffect: (env: SparkTransitionEnv) => TransitionEffect.rotate({ z: 1, angle: -90 })
    .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 })).combine(TransitionEffect.OPACITY),
  leaveEffect: (env: SparkTransitionEnv) => TransitionEffect.translate({ x: 120 })
    .combine(TransitionEffect.OPACITY)
}) { ... }

// theme: --motion-transition-duration: 300ms; --motion-transition-ease: ease-out;
// --motion-page-transition-*, --motion-transition-group-*; --motion-enabled: false → instant

过渡组 ​

STransitionGroup 为插入和移除的条目做动画;其余条目通过布局动画移动到新位置(相当于 Vue 的 FLIP move)。

arkts
@Local ids: string[] = ['Apple', 'Banana', 'Cherry'];

@LocalBuilder
renderItem(key: string) { DemoRow({ text: key }) }

STransitionGroup({ items: this.ids, itemBuilder: this.renderItem, name: 'slide-left', distance: '40vp', gap: 8 })
// assign a new array: insert / remove animate, the other rows glide to their new place
this.ids = [...];

API ​

从组件库源码中的 @Param / @Event / @BuilderParam 声明自动提取。

SSwitchTransition ​

按键切换的内容切换器(Vue 的 &lt;Transition mode> 包裹 &lt;component :is> / &lt;RouterView v-slot>):渲染 pageBuilder(current),当 current 变化时,从旧视图动画过渡到新视图。两个视图仅在过渡进行时挂载(ForEach 按 key 的插槽 + .transition(TransitionEffect.asymmetric(...)))。

  • pageBuilder 接收 key;请根据该参数构建视图(而不是根据父组件状态),这样离开的视图会保留其内容。请使用 @LocalBuilder,使 this 仍指向父组件。
  • mode:'default'(同时进行,视图在 Stack 中叠加)、'out-in'(先离开旧视图,再进入新视图)、'in-out'(先进入新视图,再离开旧视图)。
  • navDirection(之所以如此命名,是因为 direction 是通用属性):'forward' | 'back' | 'auto'。'auto' 依次比较 index(数字,例如标签索引)、order 中的位置,然后是访问历史(返回上一个 key 即为后退)。带方向的预设(slide-、zoom、shared-axis-)在后退时会反向。
  • 生命周期事件接收 key:onBeforeEnter / onAfterEnter / onBeforeLeave / onAfterLeave。
  • clipContent(默认 true)会将滑动的视图裁剪到切换器的边界之内。
属性类型默认值说明
currentstring''
nameSparkTransitionName'fade'
modeSparkTransitionMode
SparkTransitionMode = 'default' | 'out-in' | 'in-out'
'default'
navDirectionSparkNavDirection
SparkNavDirection = 'forward' | 'back' | 'auto'
'auto'
orderstring[][]供 navDirection: 'auto' 使用的有序 key(靠后的为前进)。
indexnumber-1current 的数字位置,供 navDirection: 'auto' 使用(-1 表示不使用)。
appearbooleanfalse
distancestring'100%'
clipContentbooleantrue
motionKeystring'transition'
speedSparkSpeed
SparkSpeed = 'fast' | 'normal' | 'slow'
'normal'
durationnumber-1
easestring''
enterEffectSparkTransitionEffectFactory | undefinedundefined
leaveEffectSparkTransitionEffectFactory | undefinedundefined
事件类型默认值说明
onBeforeEnter(key: string) => void() => { }
onAfterEnter(key: string) => void() => { }
onBeforeLeave(key: string) => void() => { }
onAfterLeave(key: string) => void() => { }

插槽: pageBuilder

SPageTransition ​

页面级的 SSwitchTransition(Vue 的 &lt;RouterView v-slot="{ Component }">&lt;Transition :name>):默认采用带方向的 Material 共享轴 X 动画;除非提供了 order / index,否则根据访问历史判断是否为后退。

属性类型默认值说明
currentstring''
nameSparkTransitionName'shared-axis-x'
modeSparkTransitionMode
SparkTransitionMode = 'default' | 'out-in' | 'in-out'
'default'
navDirectionSparkNavDirection
SparkNavDirection = 'forward' | 'back' | 'auto'
'auto'
orderstring[][]
indexnumber-1
appearbooleanfalse
distancestring'100%'
clipContentbooleantrue
motionKeystring'page-transition'
speedSparkSpeed
SparkSpeed = 'fast' | 'normal' | 'slow'
'normal'
durationnumber-1
easestring''
enterEffectSparkTransitionEffectFactory | undefinedundefined
leaveEffectSparkTransitionEffectFactory | undefinedundefined
事件类型默认值说明
onBeforeEnter(key: string) => void() => { }
onAfterEnter(key: string) => void() => { }
onBeforeLeave(key: string) => void() => { }
onAfterLeave(key: string) => void() => { }

插槽: pageBuilder

STransition ​

用于单个条件元素(v-if)的 Vue &lt;Transition>:show 变化时插入 / 移除内容,并通过官方的组件转场(.transition(TransitionEffect.asymmetric(...), onFinish))做动画。

时序:动效 key motionKey(默认 'transition',--motion-transition-duration\|ease\|enabled),按 speed 生效,可通过 duration(毫秒)/ ease 按实例覆盖;--motion-enabled: false 会使其立即完成。键控内容(在页面 / 视图之间切换)请使用 SSwitchTransition;列表请使用 STransitionGroup。

属性类型默认值说明
showbooleanfalse挂载(true)或移除(false)内容。
nameSparkTransitionName'fade'
appearbooleanfalse初次渲染时同样执行动画(Vue 的 appear)。
distancestring'100%''slide-*' 预设的滑动距离(长度字符串;默认为内容的 100%)。
motionKeystring'transition'
speedSparkSpeed
SparkSpeed = 'fast' | 'normal' | 'slow'
'normal'
durationnumber-1按实例设置的时长,单位毫秒(-1 表示由动效 key 决定)。
easestring''按实例设置的缓动('ease-out'、'cubic-bezier(...)'、'spring(0.4, 0.8)');'' 表示由动效 key 决定。
enterEffectSparkTransitionEffectFactory | undefinedundefined
leaveEffectSparkTransitionEffectFactory | undefinedundefined
事件类型默认值说明
onBeforeEnter() => void() => { }
onAfterEnter() => void() => { }
onBeforeLeave() => void() => { }
onAfterLeave() => void() => { }

插槽: 子组件(尾随闭包)

STransitionGroup ​

Vue 的 &lt;TransitionGroup>:按 key 排列的列表,插入 / 移除的条目使用预设(或自定义效果)做动画,其余条目则平滑滑动到新位置(Vue 的 FLIP move 类)。移动是 ArkUI 的布局动画:渲染后的列表会在 SparkAnim.runWith(animateTo + applySync)内更新,因此更新导致的位置变化与之使用相同的时长 / 曲线。

请通过赋值新数组来更新 items(this.ids = [...]);key 必须唯一且稳定。

属性类型默认值说明
itemsstring[][]
nameSparkTransitionName'fade'
axisSparkTransitionGroupAxis
SparkTransitionGroupAxis = 'vertical' | 'horizontal'
'vertical'
gapnumber0
distancestring'100%''slide-*' 预设的滑动距离(默认为条目的 100%)。
motionKeystring'transition-group'
speedSparkSpeed
SparkSpeed = 'fast' | 'normal' | 'slow'
'normal'
durationnumber-1
easestring''
enterEffectSparkTransitionEffectFactory | undefinedundefined
leaveEffectSparkTransitionEffectFactory | undefinedundefined

插槽: itemBuilder

MIT Licensed