Ir para o conteúdo
jolt.
← Receitas

LAYOUT / iOS / NATIVESCRIPT VUE

Um relógio. Todas as cenas.

O indicador preenche no mesmo relógio que avança o onboarding.

Do projeto Auralis ↗
Gravação nativa · iOSAuralis no iOS: gravação enviada pelo criador com abertura animada, cards de vidro flutuantes, três cenas de onboarding e controles de página. Velocidade original, sem áudio; os primeiros 4,25 segundos da tela inicial e transição do sistema foram omitidos. Dispositivo não informado; não é medição de desempenho. Contas e serviços são ilustrativos.

O movimento por trás.

Jolt 0.1.0-rc.11

O arquivo completo do projeto, vinculado à revisão conferida. Adapte com as dependências descritas abaixo.

Chame useCarouselClock no setup do NativeScript-Vue com um callback advance assíncrono. Vincule progress ao scaleX do indicador com originX=0, como em PageIndicator.vue. Chame hold antes de navegar e start após a cena estabilizar; conecte playing/toggle a um controle rotulado. O hook começa pausado se movimento reduzido ou leitor de tela estiver ativo no setup. Preserve a proteção por geração, o motion scope e a limpeza no unmount. Pausar mantém o timer atual; navegar manualmente reinicia o intervalo de leitura. O hook não fornece views, navegação por swipe nem listener para alterações nas preferências. Veja useOnboarding.ts para coordenação.

useCarouselClock.ts
import { onUnmounted, ref } from 'nativescript-vue'
import { isA11yEnabled } from '@nativescript/core/accessibility'
import { motionScope, motionValue, reducedMotion, set, type Animation } from '@rafaelaugusto/jolt'

export const CAROUSEL_DURATION = 4000

/** The indicator and advance share one Jolt clock: no interval or per-frame JS. */
export function useCarouselClock(advance: () => Promise<void>) {
  const progress = motionValue(0)
  const playing = ref(!reducedMotion() && !isA11yEnabled())
  const motion = motionScope()
  let timer: Animation | undefined
  let ready = false
  let generation = 0
  if (!playing.value) motion.suspend()

  function hold() {
    ready = false
    generation++
    timer?.stop()
    timer = undefined
    set(progress, 0)
  }

  function start() {
    hold()
    ready = true
    if (!playing.value || motion.disposed) return
    const current = generation
    timer = motion.animate(progress, 1, { duration: CAROUSEL_DURATION, ease: 'linear' })
    void timer.finished.then(completed => {
      if (current !== generation || !completed || motion.disposed) return
      timer = undefined
      if (ready && playing.value) void advance()
    })
  }

  function toggle() {
    playing.value = !playing.value
    if (playing.value) {
      motion.resume()
      if (ready && !timer) start()
    } else motion.suspend()
  }

  onUnmounted(() => { generation++; motion.dispose() })
  return { progress, playing, start, hold, toggle }
}
Ver demo completa ↗

Leia o guia completo ↗