Implementación de animación de apilamiento en Swiper con HarmonyOS

HarmonyOS 13 introduce la posibilidda de sustituir la transición lineal por defecto del componente Swiper mediante la propiedad customContentTransition. A continuación se describe cómo lograr que cada página nueva se deslice encima de la anterior, mantenienod la vista actual fija.

Concepto clave: SwiperContentAnimatedTransition

La función que se pasa a customContentTransition recibe un proxy que ofrece, en cada frame del gesto, la posición relativa (position), el índice de la página (index) y la longitud del eje principal (mainAxisLength). Con estos valores podemos:

  • Contrarrestar el desplazamiento por defecto aplicando una traslación opuesta.
  • Elevar la capa que entra con zIndex para que quede por encima.

Estructura de datos

Preparamos tres vectores paralelos:

@State desplazamientos: number[] = [0, 0, 0, 0];
@State profundidades:   number[] = [0, 0, 0, 0];
@State colores:        Color[]   = [Color.Red, Color.Green, Color.Blue, Color.Orange];

Detección de dirección

Antes de animar, registramos la direción del swipe para saber qué extremo del array requiere tratamiento especial:

.onGestureSwipe((_: number, ev: SwiperAnimationEvent) => {
  this.direccionIzquierda = ev.currentOffset < 0;
})

Animación personalizada

La lógica se divide en dos fases:

  1. Reposo: position vale 0 o 1; restablecemos desplazamientos y profundidades.
  2. Swipe activo: calculamos la traslación que neutraliza el movimiento de la página actual y desplazamos la siguiente.
.customContentTransition({
  timeout: 0,
  transition: (proxy: SwiperContentTransitionProxy) => {
    const { index, position, mainAxisLength } = proxy;

    // Fase de reposo
    if (position <= 0 || position >= 1) {
      if (this.direccionIzquierda) {
        const siguiente = (index + 1) % this.colores.length;
        this.desplazamientos[siguiente] = 0;
        this.profundidades[siguiente]   = 0;
      } else {
        this.desplazamientos[index] = 0;
        this.profundidades[index]   = 0;
      }
      return;
    }

    // Fase activa
    if (this.direccionIzquierda) {
      const anterior = index === 0 ? this.colores.length - 1 : index - 1;
      this.desplazamientos[anterior] = mainAxisLength * (1 - position);
      this.profundidades[anterior]   = -1;  // detrás
      this.profundidades[index]      = 1;   // encima
    } else {
      this.desplazamientos[index] = -mainAxisLength * position;
      this.profundidades[index]   = -1;     // detrás
      const anterior = index === 0 ? this.colores.length - 1 : index - 1;
      this.profundidades[anterior] = 1;     // encima
    }
  }
})

Plantilla Swiper

Enlazamos los vectores a cada página:

Swiper() {
  ForEach(this.colores, (color: Color, i: number) =>
    Text(`${i}`)
      .width('100%')
      .height('100%')
      .backgroundColor(color)
      .textAlign(TextAlign.Center)
      .translate({ x: this.desplazamientos[i] })
      .zIndex(this.profundidades[i])
  )
}
.height(200)

El resultado es un carrusel donde la página visible permanece fija y la siguiente se superpone deslizándose desde el borde correspondiente.

Etiquetas: HarmonyOS ArkTS Swiper CustomAnimation zIndex

Publicado el 8-31 19:44