{"id":20324967,"url":"https://github.com/khlebobul/magic_ball","last_synced_at":"2026-05-12T19:04:07.812Z","repository":{"id":241962499,"uuid":"804491207","full_name":"khlebobul/magic_ball","owner":"khlebobul","description":"Magic Ball with predictions using API and Rive animation","archived":false,"fork":false,"pushed_at":"2024-06-16T20:08:47.000Z","size":21326,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-14T14:21:32.955Z","etag":null,"topics":["animation","dart","flutter","rive"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/khlebobul.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-22T17:30:27.000Z","updated_at":"2024-10-25T07:29:10.000Z","dependencies_parsed_at":"2024-06-16T21:39:25.033Z","dependency_job_id":null,"html_url":"https://github.com/khlebobul/magic_ball","commit_stats":null,"previous_names":["khlebobul/magic_ball"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khlebobul%2Fmagic_ball","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khlebobul%2Fmagic_ball/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khlebobul%2Fmagic_ball/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khlebobul%2Fmagic_ball/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/khlebobul","download_url":"https://codeload.github.com/khlebobul/magic_ball/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241828270,"owners_count":20026878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","dart","flutter","rive"],"created_at":"2024-11-14T19:38:19.183Z","updated_at":"2026-05-12T19:04:02.786Z","avatar_url":"https://github.com/khlebobul.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# magic_ball\n\nMagic Ball with predictions using API and Rive animation\n\n## Demo\n\n![demo](rive_magic_ball_demo.gif)\n\n## Intro\n\nI've been wanting to try adding Rive animation to an app written in Flutter for a long time. What I need to do this:\n- Rive file: [Unlucky 8 ball - randomise feature](https://rive.app/community/files/9961-18989-unlucky-8-ball-randomise-feature/)\n- [8Ball API](https://www.eightballapi.com/docs)\n- [Rive package](https://pub.dev/packages/rive/install)\n- [http package](https://pub.dev/packages/http)\n\nUseful links:\n- [Flutter x Rive – create smooth Flutter animations](https://applover.com/blog/flutter-x-rive-create-smooth-flutter-animations/)\n- [Rive animations in Flutter](https://www.geeksforgeeks.org/rive-animations-in-flutter/)\n- [Rive for Flutter Animations](https://medium.com/@RotenKiwi/rive-for-flutter-animations-a99bfdd8f6cc)\n- [Awesome Rive](https://github.com/Roaa94/awesome-rive)\n\n---\n\nFirst, let's turn to the [Introduction page](https://help.rive.app/) and [Rive Flutter documentation](https://help.rive.app/runtimes/overview/flutter) and try to look at the basic code with the machine.\n\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:rive/rive.dart';\n\nvoid main() =\u003e runApp(MaterialApp(\n      home: MyRiveAnimation(),\n    ));\n\nclass MyRiveAnimation extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return const Scaffold(\n      body: Center(\n        child: RiveAnimation.network(\n          'https://cdn.rive.app/animations/vehicles.riv',\n          fit: BoxFit.cover,\n        ),\n      ),\n    );\n  }\n}\n```\n\nIt's very simple! Now let's try to make our own Magic Ball app that will give predictions using API when you tap on the ball.\n\nYou can find more Flutter examples [here](https://github.com/rive-app/rive-flutter/blob/master/example/lib/main.dart)\n\n## Implementation\n\nThis is not a guide on how to use Rive and Flutter. I'm just describing one particular case and adding useful material.\n\n#### 1. [Select](https://rive.app/community/files/9961-18989-unlucky-8-ball-randomise-feature/) Preview in Rive\n\nWe can add this file to ourselves after which change as we need. \nWe will be using the file via assets, so we need to download the animation file.\n\n#### 2. In the window that opens, click on the drop-down menu and select export.\n\nWe should end up with a .riv file and add it to our assets folder. In the copy of my animation, I removed the default text.\n\n#### 3. Add our downloaded animation to the project\n\nmain.dart\n```dart \nimport 'package:flutter/material.dart';\nimport 'package:magic_ball/screens/magic_ball.dart';\n\nvoid main() =\u003e runApp(const MaterialApp(\n      home: MagicBallScreen(),\n      debugShowCheckedModeBanner: false,\n    ));\n\n```\n\nmagic_ball.dart\n``` dart\nimport 'package:flutter/material.dart';\nimport 'package:rive/rive.dart';\n\nclass MagicBallScreen extends StatefulWidget {\n  const MagicBallScreen({super.key});\n\n  @override\n  State\u003cMagicBallScreen\u003e createState() =\u003e _MagicBallScreenState();\n}\n\nclass _MagicBallScreenState extends State\u003cMagicBallScreen\u003e {\n  @override\n  Widget build(BuildContext context) {\n    return const Scaffold(\n      body: Center(\n        child: RiveAnimation.asset(\n          'assets/magic_ball.riv',\n          fit: BoxFit.cover,\n        ),\n      ),\n    );\n  }\n}\n\n```\n\n#### 4. StateMachines (Add intelligence to your animations)\n\nIn this StateMachine, you can define different animation states and their transitions. For each state, you can specify an animation to play.\n\nIn our case, we need to add an action animation for clicking on the ball. To do this, we need to add an `Indle` action and `Screen on` with the message.\n\n```dart\n///\n  @override\n  void initState() {\n    super.initState();\n    _controller = SimpleAnimation('Idle');\n  }\n\n  void _onBallTapped() {\n    setState(() {\n      if (_controller.isActive) {\n        _controller = SimpleAnimation('Screen on');\n      } else {\n        _controller = SimpleAnimation('Idle');\n      }\n    });\n  }\n///\n```\n\n#### 5. Change text on the ball\n\nOur animation already has the `M01` text embedded in it, which is displayed by default. Honestly, I haven't figured out how to change the default text. Maybe someone can help me. Therefore, I propose to remove the message in the copy of our animation from block M01 and leave it without text. Let's do the new file export again.\n\nThen let's add text in the center when you click on the ball.\n\n```dart\nWidget build(BuildContext context) {\n    return Scaffold(\n      body: Stack(\n        children: [\n          Center(\n            child: GestureDetector(\n              onTap: _onBallTapped,\n              child: RiveAnimation.asset(\n                'assets/magic_ball.riv',\n                fit: BoxFit.cover,\n                controllers: [_controller],\n              ),\n            ),\n          ),\n          if (_showText)\n            const Center(\n              child: Text(\n                'Active',\n                style: TextStyle(\n                  fontSize: 18,\n                  fontWeight: FontWeight.bold,\n                  color: Colors.white,\n                ),\n              ),\n            ),\n        ],\n      ),\n    );\n  }\n```\n\nIt is also possible to add animation of text appearing smoothly. \n\n#### 6. Add text predictions from the [API](https://www.eightballapi.com/docs)\n\nWe will send the request using the [http package](https://pub.dev/packages/http)\n\napi_client.dart\n```dart\nimport 'package:http/http.dart' as http;\nimport 'dart:convert';\n\nclass ApiClient {\n  static const String _baseUrl = 'https://eightballapi.com/api';\n\n  Future\u003cString\u003e fetch8BallResponse() async {\n    try {\n      final response = await http.get(Uri.parse(_baseUrl));\n\n      if (response.statusCode == 200) {\n        final data = json.decode(response.body);\n        return data['reading'];\n      } else {\n        throw Exception('Error fetching response');\n      }\n    } catch (e) {\n      return Future.error('Error fetching response');\n    }\n  }\n}\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhlebobul%2Fmagic_ball","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkhlebobul%2Fmagic_ball","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhlebobul%2Fmagic_ball/lists"}