Animação de personagens no watchOS e visionOS
Por equipe Charmotion · Atualizado em

Nem Rive nem Lottie têm suporte oficial ao watchOS: o rive-ios declara iOS, visionOS, tvOS, macOS e Mac Catalyst, e o lottie-spm declara iOS, macOS, tvOS e visionOS. No Apple Watch, anime com PhaseAnimator ou KeyframeAnimator do SwiftUI (watchOS 10+) ou reproduza frames pré-renderizados. No visionOS, os dois funcionam em uma janela SwiftUI comum.
Principais pontos
- Package.swift do rive-ios: iOS 14, visionOS 1, tvOS 16, macOS 13.1, Mac Catalyst 14. Sem watchOS.
- O Package.swift do lottie-spm lista iOS, macOS, tvOS e visionOS. Sem watchOS.
- No watchOS, use os animators do SwiftUI ou uma sequência de frames controlada por
TimelineView. - No visionOS, um mascote 2D fica em uma janela ou ornament do SwiftUI; o RealityKit é para modelos 3D.
- Exporte os frames do vídeo com fundo transparente do mesmo personagem para que Watch, celular e Vision Pro fiquem iguais.
O Rive tem suporte ao watchOS?
Não oficialmente. As plataformas no Package.swift do rive-ios são:
platforms: [.iOS("14.0"), .visionOS("1.0"), .tvOS("16.0"), .macOS("13.1"), .macCatalyst("14.0")]
O Swift Package Manager não vincula o pacote a um target watchOS porque o watchOS não está nessa lista. Um resumo da página de migração do Rive para Apple já deu a entender, em alguns momentos, que o novo runtime suporta watchOS, mas é o manifesto publicado que o Xcode aplica, então planeje como se o Rive não estivesse disponível no Watch. Confira o manifesto de novo ao atualizar o pacote, já que as listas de plataformas podem mudar entre versões.
O mesmo vale para o runtime legado do Rive: os dois runtimes vêm em um único pacote com um único conjunto de plataformas. Se o seu app de iPhone e o app do Watch compartilham um pacote Swift de componentes de UI, mantenha as views que usam Rive em um módulo do qual só os targets iOS (e visionOS) dependem, ou o build do Watch não vai conseguir resolver a dependência.
O Lottie tem suporte ao watchOS?
Não. O manifesto do lottie-spm, que a Airbnb recomenda para o Swift Package Manager, declara iOS, macOS, tvOS e visionOS. Não há entrada para watchOS.
| Opção | iOS | visionOS | watchOS |
|---|---|---|---|
| RiveRuntime (rive-ios) | 14.0+ | 1.0+ | Não declarado |
| Lottie (lottie-spm) | Yes | Yes | Não declarado |
| SwiftUI PhaseAnimator / KeyframeAnimator | 17.0+ | 1.0+ | 10.0+ |
| Sequência de frames com TimelineView do SwiftUI | Yes | Yes | Yes |
| AVKit VideoPlayer | Yes | Yes | Yes |
Para as versões mínimas exatas do Lottie, leia a linha platforms da versão que você fixar.
Existem forks antigos e ports da comunidade do Lottie para watchOS, mas eles não são o pacote da Airbnb e a manutenção varia. Para um app que você pretende continuar atualizando, as opções nativas das linhas de baixo são a escolha de menor risco: vêm com o sistema, seguem as configurações de acessibilidade e não exigem dependência extra no target do Watch.
O que posso usar no Apple Watch no lugar?
Três opções, da mais leve à mais pesada:
- Animators do SwiftUI sobre uma imagem estática.
phaseAnimatorekeyframeAnimatorestão disponíveis a partir do watchOS 10. Um quique, inclinação ou pulsação em uma única pose não exige nenhum arquivo além de uma imagem. Veja PhaseAnimator vs KeyframeAnimator. - Uma sequência de frames. Exporte um loop curto como PNGs numerados, adicione-os ao asset catalog do app do Watch e percorra-os com
TimelineView. Isso mantém o movimento real do personagem (piscadas, acenos) em troca de um app maior. - Vídeo. O
VideoPlayerdo AVKit para SwiftUI está disponível no watchOS. Ele mostra os controles do player e serve mais para um clipe que o usuário escolhe assistir do que para um mascote de ambiente.
Uma view com sequência de frames:
import SwiftUI
struct FrameSequence: View {
let frames: [String] // ["wave_00", "wave_01", ...] in the asset catalog
var fps: Double = 12
@Environment(\.accessibilityReduceMotion) private var reduceMotion
var body: some View {
if reduceMotion || frames.count < 2 {
Image(frames.first ?? "")
.resizable()
.scaledToFit()
} else {
TimelineView(.animation(minimumInterval: 1 / fps)) { context in
let tick = Int(context.date.timeIntervalSinceReferenceDate * fps)
Image(frames[tick % frames.count])
.resizable()
.scaledToFit()
}
}
}
}
// Usage
FrameSequence(frames: (0..<24).map { String(format: "wave_%02d", $0) })
.frame(width: 80, height: 80)
Mantenha os loops curtos e leves: a tela do Watch é minúscula e cada frame aumenta o app. Reproduza a sequência em um momento específico (um treino concluído, um lembrete) em vez de deixá-la em loop o dia todo.
Como exporto frames para watchOS a partir do meu conjunto de animações?
Comece de uma fonte com fundo transparente para que o personagem fique limpo sobre o fundo preto do Watch. Com ffmpeg e um WebM VP9 com canal alfa:
# 12 fps, 160 px wide, keep transparency
ffmpeg -c:v libvpx-vp9 -i wave.webm -vf "fps=12,scale=160:-1" wave_%02d.png
Depois, arraste os PNGs para o asset catalog do target do Watch. Dicas:
- Dimensione para a tela. Exporte no maior tamanho em pontos que você exibe multiplicado pela escala da tela, não na resolução da fonte.
- Encurte o loop. Um loop de dois segundos a 12 fps tem 24 imagens; muitas vezes isso basta para um idle ou um wave.
- Escolha uma imagem estática para Reduzir Movimento. O primeiro frame serve também como pose estática.
Os conjuntos do Charmotion nos planos pagos incluem arquivos WebM transparentes e MOV HEVC com alfa para cada animação, junto com o .riv usado no iPhone, então os frames do Watch vêm exatamente do mesmo movimento do app do celular.
O Rive roda no visionOS?
Sim. O visionOS 1.0 está na lista de plataformas do rive-ios, e o manifesto do Lottie também inclui o visionOS. No Vision Pro, um app SwiftUI mostra suas views em janelas, então o mesmo código que você usa no iPhone funciona:
import SwiftUI
import RiveRuntime
struct MascotWindow: View {
@StateObject private var model = CharacterModel() // loads the .riv and keeps the view model instance
var body: some View {
RiveUIViewRepresentable(rive: model.rive)
.frame(width: 320, height: 320)
.padding(32)
.glassBackgroundEffect()
.task { await model.load() }
}
}
CharacterModel aqui é o controlador de Data Binding do Rive em SwiftUI: ele cria o Worker, o File, a instância do view model e a state machine vinculada. glassBackgroundEffect() é o material de vidro do visionOS; deixe de fora nas outras plataformas.
Teste no dispositivo, além do simulador. A renderização é baseada em Metal nos dois runtimes, e o peso visual de um personagem plano flutuando em um ambiente é difícil de avaliar na tela de um Mac.
No visionOS, um mascote 2D deve ficar em uma janela SwiftUI ou no RealityKit?
Mantenha um personagem 2D no SwiftUI. RealityKit e Reality Composer Pro foram feitos para conteúdo 3D: modelos, materiais e animação por esqueleto. Um personagem plano de Rive ou Lottie colocado no RealityKit não ganha nada e perde a API simples baseada em views.
| Posicionamento | Use para |
|---|---|
| Dentro da janela principal | Onboarding, estados vazios, avatar de assistente: igual ao iPhone |
| Ornament preso a uma janela | Um pequeno ajudante fixo ao lado do seu conteúdo |
| Janela pequena separada | Um companheiro que o usuário pode mover de lugar |
| Entidade do RealityKit | Só se o personagem for um modelo 3D de verdade |
O Reduzir Movimento importa ainda mais em um headset, onde o movimento ocupa uma parte maior do campo de visão. Leia @Environment(\.accessibilityReduceMotion) (disponível no visionOS 1) e pause ou troque por uma pose parada; veja Reduzir Movimento em SwiftUI e UIKit.
Adicione uma animação de personagem a um app de Apple Watch
- Escolha o método. Use um animador do SwiftUI sobre uma pose parada para movimentos simples, ou uma sequência de frames para movimento real de personagem.
- Exporte os frames. Rode
ffmpeg -c:v libvpx-vp9 -i wave.webm -vf "fps=12,scale=160:-1" wave_%02d.pngem um WebM com fundo transparente. - Adicione ao target do Watch. Arraste os PNGs para o asset catalog do app do Watch.
- Reproduza. Alterne as imagens com
TimelineView(.animation(minimumInterval:))na taxa de frames da exportação. - Trate o Reduzir Movimento. Mostre o primeiro frame como imagem parada quando
accessibilityReduceMotionfor verdadeiro.
Perguntas frequentes
Posso compartilhar o código da minha view Rive de iOS com um target watchOS?
Não diretamente, porque o pacote RiveRuntime não declara watchOS e não é vinculado a um target do Watch. Envolva o mascote em uma view sua com condicionais de plataforma: Rive no iOS e no visionOS, uma sequência de frames ou um animador do SwiftUI no watchOS, todos alimentados pelo mesmo valor de mood.
Um GIF roda no Apple Watch?
O Image do SwiftUI não anima GIFs em nenhuma plataforma Apple. Decodifique os frames do GIF em imagens e alterne entre elas, ou, melhor ainda, exporte frames PNG de uma fonte com fundo transparente e reproduza com TimelineView. Assim você controla a taxa de frames, o tamanho e o Reduzir Movimento.
O Lottie está disponível no visionOS?
Sim. O manifesto do lottie-spm declara visionOS junto com iOS, macOS e tvOS, então o LottieView funciona em uma janela SwiftUI do visionOS do mesmo jeito que no iPhone. O pacote do Rive também declara visionOS 1.0, então os dois runtimes são opções para um personagem 2D em uma janela ou ornament do visionOS.
Respostas rápidas deste guia
Fontes
- rive-ios Package.swift, Rive (GitHub)
- lottie-spm Package.swift, Airbnb (GitHub)
- PhaseAnimator, Apple
- TimelineView, Apple
- VideoPlayer (AVKit for SwiftUI), Apple
- accessibilityReduceMotion, Apple
- Apple runtime (new and legacy), Rive