spine_flutter 0.1.2 copy "spine_flutter: ^0.1.2" to clipboard
spine_flutter: ^0.1.2 copied to clipboard

outdated

The spine-flutter runtime provides functionality to load and manipulate Spine skeletal animation data using Flutter.

example/lib/main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:spine_flutter/spine_flutter.dart';

/// \see http://ru.esotericsoftware.com/spine-runtimes-guide
void main() => runApp(const MyApp());

/// All animations. Format: `model_name: defaultAnimation`.
const Map<String, String> all = <String, String>{
  'cauldron': 'idle',
  'girl_and_whale_polygons': 'idle',
  'girl_and_whale_rectangles': 'idle',
  'owl': 'idle',
  'raptor': 'walk',
  'spineboy': 'walk',
};

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'Flutter Spine Demo',
        theme: ThemeData(primarySwatch: Colors.blue),
        home: const MyHomePage(),
      );
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const String pathPrefix = 'assets/';

  String name = all.keys.last;

  late Set<String> animations;
  late SkeletonAnimation skeleton;

  @override
  Widget build(BuildContext context) => _buildFuture();

  Widget _buildFuture() => FutureBuilder<bool>(
        future: load(),
        builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
          if (snapshot.hasData) {
            if (animations.isNotEmpty) {
              final String defaultAnimation = all[name]!;
              skeleton.state.setAnimation(0, defaultAnimation, true);
            }

            return _buildScreen();
          }

          return Container();
        },
      );

  Widget _buildScreen() {
    final SkeletonRenderObjectWidget skeletonWidget =
        SkeletonRenderObjectWidget(
      skeleton: skeleton,
      alignment: Alignment.center,
      fit: BoxFit.contain,
      playState: PlayState.playing,
      debugRendering: false,
      triangleRendering: true,
    );

    final List<Widget> models = <Widget>[];
    for (final String model in all.keys) {
      models.add(
        TextButton(
          child: Text(model.toUpperCase()),
          onPressed: () async {
            name = model;
            await load();
            setState(() {
              final String defaultAnimation = all[name]!;
              skeleton.state.setAnimation(0, defaultAnimation, false);
            });
          },
        ),
      );
    }

    final List<Widget> states = <Widget>[];
    for (final String animation in animations) {
      states.add(
        TextButton(
          child: Text(animation.toLowerCase()),
          onPressed: () {
            final String defaultAnimation = all[name]!;
            skeleton.state
              ..setAnimation(0, animation, false)
              ..addAnimation(0, defaultAnimation, true, 0.0);
          },
        ),
      );
    }

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(title: Text(name)),
      body: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          skeletonWidget,
          Positioned.fill(
            child: Wrap(
              runAlignment: WrapAlignment.start,
              children: models,
            ),
          ),
          Positioned.fill(
            child: Wrap(
              runAlignment: WrapAlignment.end,
              children: states,
            ),
          ),
        ],
      ),
    );
  }

  Future<bool> load() async {
    animations = await loadAnimations();
    skeleton = await loadSkeleton();

    return true;
  }

  Future<Set<String>> loadAnimations() async {
    final String skeletonFile = '$name.json';
    final String s =
        await rootBundle.loadString('$pathPrefix$name/$skeletonFile');
    final Map<String, dynamic> data = json.decode(s);

    return ((data['animations'] ?? <String, dynamic>{}) as Map<String, dynamic>)
        .keys
        .toSet();
  }

  Future<SkeletonAnimation> loadSkeleton() async =>
      SkeletonAnimation.createWithFiles(name, pathBase: pathPrefix);
}
21
likes
0
pub points
89%
popularity

Publisher

unverified uploader

The spine-flutter runtime provides functionality to load and manipulate Spine skeletal animation data using Flutter.

Homepage
Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter, spine_core

More

Packages that depend on spine_flutter