Embed and control hosted Spline 3D/interactive scenes inside your Flutter apps with a simple widget + controller API powered by webview_flutter.

Features

  • Display a Spline scene by URL with SplineViewer.
  • Imperative control via SplineController (reload, run/evaluate JS helpers).
  • Loading placeholder & error builder customization.
  • Optional zoom enablement.

Getting started

Add dependency in pubspec.yaml (already done if you're reading the source):

dependencies:
	spline_flutter: ^0.0.1

Ensure your platform setup (iOS minimum, Android WebView) follows webview_flutter requirements.

Usage

Basic

final controller = SplineController();

SplineViewer(
	sceneUrl: 'https://my.spline.design/your-scene-url',
	controller: controller,
	enableZoom: true,
	placeholder: const Center(child: CircularProgressIndicator()),
	errorBuilder: (context, error) => Center(child: Text('Failed: $error')),
);

Run JavaScript / helpers

controller.play(); // attempts to call window.spline.play()
controller.pause();
await controller.runJavaScript("console.log('Hello from Flutter');");
final value = await controller.evaluateJavaScript('2 + 2');

Runtime (.splinecode) mode

If you exported a Spline scene as .splinecode, pass that URL (or a self-hosted URL) instead of the hosted page. The widget detects the suffix and boots the Spline Runtime inside a lightweight HTML shell.

final controller = SplineController()
	..onLoaded = () => debugPrint('Runtime scene loaded')
	..onMessage = (m) => debugPrint('Raw message: $m');

SplineViewer(
	sceneUrl: 'https://prod.spline.design/xxxx/scene.splinecode',
	controller: controller,
);

// Add event listeners
final mouseDownId = controller.addEventListener('mouseDown', (payload) {
	debugPrint('mouseDown event: $payload');
});

// Later remove
controller.removeEventListenerById(mouseDownId);

// Switch to another scene code file
await controller.loadSceneUrl('https://prod.spline.design/yyyy/scene.splinecode');

Events are relayed through addEventListener; payload includes a target with id, name, and basic transforms when available.

Dispose the controller only if you created it and the viewer is unmounted.

Additional information

Planned improvements:

  • Event channel for richer Spline runtime events (selection, camera moves).
  • Support for offline/embedded export bundles.
  • Example app under /example.

Contributions & issues welcome.

License

MIT. See LICENSE file.