rive-flutter icon indicating copy to clipboard operation
rive-flutter copied to clipboard

Question: How can I replace a component?

Open dbdev77 opened this issue 2 years ago • 4 comments

I have a .riv file which contains a static svg image (without any animations).

File structure: artboard->image.svg/group1/group2/(groupA/groupB/groupC). Groups A, B, C contain various shapes, ellipses, etc.

I have two questions:

  1. Can I change the visibility of groupC so that the image does not show objects from this group?

  2. Can I remove groupC and add groupD to the file instead? I have tried removing the group in many different ways, but the image stays the same.

     RiveFile riveFile = await RiveFile.asset('assets/images/rive.riv');
     var set = riveFile.mainArtboard
         .children.elementAt(0)        // image.svg
         .dependents.elementAt(0) // group1
         .dependents.elementAt(0) //group2
         .dependents;                       //groupA/groupB/groupC

     var groupC = set.firstWhere((element) => element.name == 'groupC');

     groupC.remove();
     groupC.onRemoved();

    ...

    return Scaffold(
      body: Center(
        child: Rive(
          artboard: riveFile!.mainArtboard,
          fit: BoxFit.fitWidth,
          alignment: Alignment.center,
        ),
      ),
    );

I would appreciate your help, thanks.

dbdev77 avatar Mar 25 '23 12:03 dbdev77

Hi! At the moment we don't expose an API to achieve the component swapping like you mentioned. You can delve down a deeper level and potentially achieve the results you are looking for at a painting level. Take a look at this sample repo demoing how to change the opacity/color of components: https://github.com/HayesGordon/rive_flutter_runtime_color_change_example

We will be releasing a new feature soon, called Solos, this will allow you to turn certain components on/off (for example you define A, B, and C and then you can choose to display one of those and turn the others off) - which means you'll be able to easily configure this within the editor and it'll be an efficient way to do it. You can technically already do this by setting up multiple animations (that hide show relevant sections) and controlling it with a state machine.

HayesGordon avatar Mar 29 '23 14:03 HayesGordon

Solos has release, more information for anyone interested: https://www.youtube.com/watch?v=4z364R6YpJw

HayesGordon avatar Apr 13 '23 09:04 HayesGordon

Solos has release, more information for anyone interested: https://www.youtube.com/watch?v=4z364R6YpJw

Thank you! Could you provide a link to a usage example on flutter?

dbdev77 avatar Apr 21 '23 11:04 dbdev77

Here is some example code. It'll require you to import src code that is not exported in the library. In the future there may be a better API to do this.

import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
// NOTE THESE IMPORTS
import 'package:rive/src/rive_core/solo.dart';
import 'package:rive/src/container_children.dart';

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

  @override
  State<SoloSwitchExample> createState() => _SoloSwitchExampleState();
}

class _SoloSwitchExampleState extends State<SoloSwitchExample> {
  late Solo mySolo;
  late ContainerChildren soloChildren;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
                onPressed: () {
                  // Switch between the two children in the SOLO. You can
                  // make this more robust. This is just an example
                  if (mySolo.activeComponent == soloChildren[0]) {
                    mySolo.activeComponent = soloChildren[1];
                  } else {
                    mySolo.activeComponent = soloChildren[0];
                  }
                },
                child: const Text('go')),
            Expanded(
              child: RiveAnimation.asset(
                'assets/solo_sample.riv',
                fit: BoxFit.cover,
                onInit: (artboard) {
                  // This is where you can get the Solo object
                  for (var element in (artboard as RuntimeArtboard).objects) {
                    if (element is Solo) {
                      print(element.name);
                      for (var element in element.children) {
                        print(element.name);
                      }
                      mySolo = element;
                      soloChildren = mySolo.children;
                    }
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

If you have multiple solos you should also do a check to make sure the name matches. For example:

if (element.name == "MySolo") // do something

https://github.com/rive-app/rive-flutter/assets/13705472/83a60d5b-d5e7-4396-b47e-222d8cf532a0

HayesGordon avatar May 10 '23 15:05 HayesGordon

I'm closing this issue for now as Component swapping is not something we're looking into supporting directly through our high-level runtimes.

HayesGordon avatar Aug 12 '24 14:08 HayesGordon