Ir al contenido
jolt.
← Recetas

MOVIMIENTO / iOS / NATIVESCRIPT VUE

Un ritmo propio.

Una señal trazada, un título suave y la entrada escalonada de Vena.

Del proyecto Vena ↗
Grabación nativa · iOSVena en iOS: grabación del creador, con interfaz en inglés, apertura, corazón de partículas, colección de ritmos y enfoque del corazón. Velocidad original, exportación a 60 fps, sin audio; se omiten los primeros 3,25 segundos del inicio del sistema. Dispositivo no especificado; no mide rendimiento. Valores de BPM ilustrativos. BodyParts3D © DBCLS · CC BY 4.0 / MakeHuman · CC0 ↗

El movimiento detrás.

Jolt 0.1.0-rc.11

El archivo completo del proyecto, fijado a la revisión verificada. Adáptalo con las dependencias descritas abajo.

NativeScript-Vue 3 y Jolt RC.11. Llama a opening con cuatro vistas nativas cargadas; title, caption y skip comienzan con opacity 0. rule aloja un trazado de 190×30. WelcomeOverlay.vue muestra la protección al terminar/saltar y la limpieza. revealInterface recibe un MotionScope propio y cuatro vistas montadas. Libera el handle de opening y el scope al salir. Este archivo anima texto, trazado y entrada; el corazón necesita HeartScene y sus recursos. Conserva el movimiento reducido. Grabación en iOS.

entrance.ts
import type { View } from '@nativescript/core'
import { motionScope, reducedMotion, set, type MotionScope } from '@rafaelaugusto/jolt'
import { shape, type Shape } from '@rafaelaugusto/jolt/shapes'

export interface EntranceTargets { title: View; caption: View; rule: View; skip: View }

export function opening(targets: EntranceTargets) {
  const scope = motionScope()
  const drawings: Shape[] = []
  if (reducedMotion()) {
    set([targets.title, targets.caption, targets.skip], { opacity: 1 })
    return { scope, finished: scope.animate(targets.title, { opacity: [1, 1] }, { duration: 180 }).finished, dispose: () => scope.dispose() }
  }
  const line = shape(targets.rule, { viewBox: [0, 0, 190, 30], d: 'M0 15 L47 15 L56 12 L62 15 L76 15 L82 21 L89 2 L97 28 L105 15 L123 15 Q134 5 144 15 L190 15', fill: 'transparent', stroke: '#FF4067', strokeWidth: 1.1, strokeEnd: 0, lineCap: 'round' })
  drawings.push(line)
  const sequence = scope.timeline([
    [targets.title, { opacity: [0, 1], y: [14, 0] }, { at: 420, duration: 800, ease: 'easeOut' }],
    { at: 700, run: () => line.animate({ strokeEnd: 1 }, { duration: 1000, ease: 'easeInOut' }) },
    [targets.caption, { opacity: [0, 1], y: [8, 0] }, { at: 1000, duration: 600, ease: 'easeOut' }],
    [targets.skip, { opacity: [0, .7] }, { at: 1200, duration: 500 }],
    [targets.title, { opacity: [1, 1] }, { at: 2100, duration: 350 }],
  ])
  return { scope, finished: sequence.finished, dispose() { scope.dispose(); drawings.forEach(drawing => drawing.dispose()) } }
}

export function revealInterface(scope: MotionScope, header: View, card: View, footer: View, hint: View) {
  return scope.timeline([
    [header, { opacity: [0, 1], y: reducedMotion() ? 0 : [-9, 0] }, { at: 0, duration: 500, ease: 'easeOut' }],
    [card, { opacity: [0, 1], y: reducedMotion() ? 0 : [38, 0] }, { at: 100, type: 'spring', duration: 850, bounce: .12 }],
    [footer, { opacity: [0, 1], y: reducedMotion() ? 0 : [12, 0] }, { at: 230, duration: 600, ease: 'easeOut' }],
    [hint, { opacity: [0, .7] }, { at: 600, duration: 600 }],
  ])
}
Ver demo completa ↗

Lee la guía completa ↗