Monty  Boehm

Monty Boehm

1684237440

Component-wrapper for Collapse animation with React-motion

React-collapse

Component-wrapper for collapse animation for elements with variable (and dynamic) height

React Collapse

Installation

NPM

npm install --save react-collapse

yarn

yarn add react-collapse

1998 Script Tag:

<script src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-collapse/build/react-collapse.min.js"></script>
(Module exposed as `ReactCollapse`)

Usage

1. Add a CSS transition

.ReactCollapse--collapse {
  transition: height 500ms;
}

IMPORTANT: Without adding a CSS transition there will be no animation and component will open/close instantly.

2. Content is always mounted (default)

import {Collapse} from 'react-collapse';

// ...
<Collapse isOpened={true || false}>
  <div>Random content</div>
</Collapse>

3. Content unmounts when collapsed

Use Unmount component provided as:

import {UnmountClosed} from 'react-collapse';

// ...
<UnmountClosed isOpened={true || false}>
  <div>Random content</div>
</UnmountClosed>

Example example/App/AutoUnmount.js


4. Controlled and accessible

If you want a controlled and accessible implementation, check out this example

Options

isOpened: PropTypes.boolean.isRequired

Expands or collapses content.

children: PropTypes.node.isRequired

One or multiple children with static, variable or dynamic height.

<Collapse isOpened={true}>
  <p>Paragraph of text</p>
  <p>Another paragraph is also OK</p>
  <p>Images and any other content are ok too</p>
  <img src="nyancat.gif" />
</Collapse>

theme: PropTypes.objectOf(PropTypes.string)

It is possible to set className for extra div elements that ReactCollapse creates.

Example:

<Collapse theme={{collapse: 'foo', content: 'bar'}}>
  <div>Customly animated container</div>
</Collapse>

Default values:

const theme = {
  collapse: 'ReactCollapse--collapse',
  content: 'ReactCollapse--content'
}

Which ends up in the following markup:

<div class="ReactCollapse--collapse">
  <div class="ReactCollapse--content">
    {children}
  </div>
</div>

IMPORTANT: these are not style objects, but class names!

onRest, onWork: PropTypes.func

Callback functions, triggered when animation has completed (onRest) or has just started (onWork)

Both functions are called with argument:

const arg = {
  isFullyOpened: true || false, // `true` only when Collapse reached final height
  isFullyClosed: true || false, // `true` only when Collapse is fully closed and height is zero
  isOpened: true || false, // `true` if Collapse has any non-zero height
  containerHeight: 123, // current pixel height of Collapse container (changes until reaches `contentHeight`)
  contentHeight: 123 // determined height of supplied Content
}
<Collapse onRest={console.log} onWork={console.log}>
  <div>Container text</div>
</Collapse>

Example example/App/Hooks.js

initialStyle: PropTypes.shape

initialStyle: PropTypes.shape({
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  overflow: PropTypes.string
})

You may control initial element style, for example to force initial animation from 0 to height by using initialStyle={{height: '0px', overflow: 'hidden'}}

IMPORTANT Any updates to this prop will be ignored after first render. Default value is determined based on initial isOpened value:

  initialStyle = props.isOpened
    ? {height: 'auto', overflow: 'initial'}
    : {height: '0px', overflow: 'hidden'};

Example: example/App/ForceInitialAnimation.js

checkTimeout: PropTypes.number

Number in ms.

Collapse will check height after thins timeout to determine if animation is completed, the shorter the number - the faster onRest will be triggered and the quicker height: auto will be applied. The downside - more calculations. Default value is: 50.

Pass-through props

IMPORTANT Collapse does not support any pass-through props, so any non-supported props will be ignored

Because we need to have control over when Collapse component is updated and it is not possible or very hard to achieve when any random props can be passed to the component.

Behaviour notes

initially opened Collapse elements will be statically rendered with no animation. You can override this behaviour by using initialStyle prop

due to the complexity of margins and their potentially collapsible nature, ReactCollapse does not support (vertical) margins on their children. It might lead to the animation "jumping" to its correct height at the end of expanding. To avoid this, use padding instead of margin. See #101 for more details

Migrating from v4 to v5

v5 was another complete rewrite that happened quite a while ago, it was published as @nkbt/react-collapse and tested in real projects for a long time and now fully ready to be used.

In the most common scenario upgrade is trivial (add CSS transition to collapse element), but if you were using a few deprecated props - there might be some extra work required.

Luckily almost every deprecated callback or prop has fully working analogue in v5. Unfortunately not all of them could maintain full backward compatibility, so please check this migration guide below.

1. Change in behaviour

New Collapse does not implement animations anymore, it only determines Content height and updates Collapse wrapper height to match it. Only after Collapse height reaches Content height (animation finished), Collapse's style is updated to have height: auto; overflow: initial.

The implications is that you will need to update your CSS with transition:

.ReactCollapse--collapse {
  transition: height 500ms;
}

IMPORTANT: Without adding a CSS transition there will be no animation and component will open/close instantly.

2. New props or updated props

onRest/onWork callbacks (see above for full description). Though onRest did exist previously, now it is called with arguments containing few operational params and flags.

initialStyle you may control initial element style, for example to force initial animation from 0 to height by using initialStyle={{height: '0px', overflow: 'hidden'}} IMPORTANT Any updates to this prop will be ignored after first render. Default value is:

  initialStyle = props.isOpened
    ? {height: 'auto', overflow: 'initial'}
    : {height: '0px', overflow: 'hidden'};

checkTimeout number in ms. Collapse will check height after thins timeout to determine if animation is completed, the shorter the number - the faster onRest will be triggered and the quicker height: auto will be applied. The downside - more calculations. Default value is: 50.

3. Deprecated props (not available in v5)

Pass-through props - any unknown props passed to Collapse component will be ignored

hasNestedCollapse - no longer necessary, as v5 does not care if there are nested Collapse elements, see example/App/Nested.js

fixedHeight - no longer necessary, just set whatever height you need for content element and Collapse will work as expected, see example/App/VariableHeight.js

springConfig - as new Collapse relies on simple CSS transitions (or your own implementation of animation) and does not use react-collapse, springConfig is no longer necessary. You can control control animation with css like

.ReactCollapse--collapse {
  transition: height 500ms;
}

forceInitialAnimation - you can use new prop initialStyle={{height: '0px', overflow: 'hidden'}} instead, so when new height will be set after component is rendered - it should naturally animate.

onMeasure - please use onRest and onWork instead and pick contentHeight from argument

<Collapse
  onRest={({contentHeight}) => console.log(contentHeight)}
  onWork={({contentHeight}) => console.log(contentHeight)}>
  <div>content</div>
</Collapse>

onRender - since animations are fully controlled by external app (e.g. with CSS) we no draw each frame and do not actually re-render component anymore, so it is impossible to have onRender callback

Development and testing

Currently is being developed and tested with the latest stable Node on OSX.

To run example covering all ReactCollapse features, use yarn start, which will compile example/Example.js

git clone git@github.com:nkbt/react-collapse.git
cd react-collapse
yarn install
yarn start

# then
open http://localhost:8080

Tests

# to run ESLint check
yarn lint

# to run tests
yarn test

Demo

http://nkbt.github.io/react-collapse

Codepen demo

http://codepen.io/nkbt/pen/MarzEg


Download Details:

Author: nkbt
Source Code: https://github.com/nkbt/react-collapse 
License: MIT license

#react #motion #component #wrapper 

Component-wrapper for Collapse animation with React-motion

A Beautiful Designed toast with animations for Flutter

Motion Toast


A well designed toast with animations for all platforms Support material3 themes

center_motion_toast.gifcenter_motion_toast_2.gifmotion_toast_bounce.gif
motion_toast_from_left.gifmotion_toast_from_right.giftop_top_animation.gif

Features

  • Animated toasts with animated icons
  • Built-in types (Success, Warning, Error, Info, Delete)
  • Possibility to design your own toast
  • Different color themes (mutliple colors support)
  • Support null safety
  • Heartbeat animations
  • Full customized text
  • Built in animations
  • Customize toast layout (LTR/RTL)
  • Customize toast duration
  • Customize Motion toast position (Center, Bottom, Top)
  • Support long text
  • Background style customization
  • Display simultaneous toasts
  • Customizable barrier color
  • Enable dismiss when toast is displayed (top, center, bottom)
  • Responsive toast according to device size
  • Customizable width and height
  • Customizable box constraints
  • Customizable toast padding
  • Customizable border display
  • Customizable sidebar widget display

Getting Started

In order to add motion toast to your project add this line to your pubspec.yaml file

dependencies:
	motion_toast: ^2.6.7

Or you can reference the main repository directly by adding those lines

dependencies:
	motion_toast:
		git: https://github.com/koukibadr/Motion-Toast.git

Attributes


/// the text widget used for description message
final  Widget description;

/// The title of the motion toast
/// if it's null it will not be rendered in the widget
final  Widget? title;

/// The motion toast type possible values:
/// sucess
/// error
/// warning
/// info
/// delete
/// custom
late  final  MotionToastType motionToastType;

  

/// The motion toast icon, for types other than custom
/// the icon will get the default type icon
/// if [motionToastType] set to [MotionToastType.custom] the icon parameter is required
late  final  IconData icon;

/// The motion toast background color
/// if `motionToastType == MOTION_TOAST_TYPE.CUSTOM` color parameter is required
/// else the color will get the default type color from [motionToastColors]
late  final  Color primaryColor;

/// Color applied on the motion toast side widget (sidebar) and the icon
/// if it's null secondary color will be the primary color
/// can be customized when using the default constructor
late  final  Color? secondaryColor;


/// the type of the background that will be applied on the motion toast content
/// available values:
/// - solid: the primary color will be applied as it is on the content background
/// - transparent: an opacity will be added to the primary color
/// - lighter: a white background added to the motion toast with little opacity added to the primary color
late  final  BackgroundType backgroundType;


/// The design type icon (Material design or Cupertino)
/// if [motionToastType] set to [MOTION_TOAST_TYPE.CUSTOM]  [iconType] will not be used
/// possible values
/// MATERIAL_DESIGN,
/// CUPERTINO
late  final  IconType? iconType;

/// The motion toast width by default it's set to 250
final  double? width;

/// define the height of the motion toast
final  double? height;

/// The constraint of the motion toast to size itself to the content
/// for responsive design
/// If it's `null`, then [width] and [height] will be used as it is.
final  BoxConstraints? constraints;

/// the motion toast icon size
/// by default it's 40
final  double iconSize;


/// disable or enable the heartbeat animation on the icon
/// by default the animation is enabled
final  bool enableAnimation;

/// The layout ToastOrientation (from right to left or from left to right)
/// {
/// LTR,
/// RTL
/// }
final  ToastOrientation layoutOrientation;

  

/// The type of animation, by default it's [AnimationType.fromBottom]
/// {
/// FROM_BOTTOM,
/// FROM_LEFT,
/// FROM_RIGHT
final  AnimationType animationType;


/// the Duration of the toast animation
/// by default it's 1.5 seconds
final  Duration animationDuration;

/// How long the toast will be shown
/// by default it's 3 seconds.
final  Duration toastDuration;

/// The toast animation curve
/// by default it's `Curves.ease`
final  Curve animationCurve;

/// The position where the motion toast will be displayed
/// possible values
/// CENTER,
/// TOP,
/// BOTTOM
final  MotionToastPosition position;

/// Define the border radius of the toast
/// by default it's 20
final  double borderRadius;

/// Function invoked when the toast is closed
final  Function? onClose;

/// define whether the motion toast can be dismissed or not
/// applied on bottom motion toast
final  bool dismissable;

/// The barrier color applied to the dialog display
/// by default the barrier is transparent [Colors.transparent]
final  Color barrierColor;

///padding added to the main widget motion taost
///by default the padding is set to 0
final  EdgeInsets padding;

/// define whether the borders are rendered or not
  /// by default  `= false`
  final bool displayBorder;

  /// define whether the side bar is displayed or not
  /// default `= true`
  final bool displaySideBar;

When creating you custom toast you don't have to use iconType it will not be used when rendering the toast

if secondaryColor not defined sidebar and icon will be rendered with primaryColor

if constraint and width and height are not defined the toast will be displayed with


BoxConstraints(
	maxWidth: MediaQuery.of(context).size.width * 0.75,
	minWidth: 200,
	maxHeight: 100,
)

otherwise if width and height are defined the constraints attribute will be ignored

and if you define width you need to define height also and vice versa

Implementation

  • Success Motion Toast

MotionToast.success(
	title:  Text("Success Motion Toast"),
	description:  Text("Example of success motion toast"),
).show(context);

  • Warning Motion Toast

MotionToast.warning(
	title:  Text("Warning Motion Toast"),
	description:  Text("This is a Warning")
).show(context);

  • Error Motion Toast

MotionToast.error(
	title:  Text("Error"),
	description:  Text("Please enter your name")
).show(context);

  • Info Motion Toast

MotionToast.info(
	title:  Text("Info Motion Toast"),
	description:  Text("Example of Info Toast")
).show(context);

  • Delete Motion Toast
MotionToast.delete(
	title:  Text("Deleted"),
	description:  Text("The item is deleted")
).show(context);

  • Custom Motion Toast

To create your custom toast just use the default constructor,

icon description and color are required


MotionToast(
	icon:  Icons.alarm,
	primaryColor:  Colors.pink,
	title:  Text("Custom Toast"),
	description:  Text("You can customize the toast!"),
	width:  300,
	height:  100,
).show(context);

  • Right-Designed Motion Toast

To change the toast layout you need to use layoutOrientation,

icon description and color are required

MotionToast.success(
	title:  Text("من اليمين"),
	description:  Text("هذا مثال بالعربية"),
	layoutOrientation:  ToastOrientation.rtl,
	animationType:  AnimationType.fromRight,width:  300,
).show(context);
  • Top-displayed Motion Toast

To change the display position of the motion toast use position attribute


MotionToast(
	icon:  Icons.zoom_out,
	color:  Colors.deepOrange,
	title:  Text("Top Motion Toast"),
	description:  Text("Another motion toast example"),
	position: MotionToastPosition.top,
	animationType:  AnimationType.fromTop,
).show(context);

  • Center-displayed Motion Toast

  

MotionToast(
	icon:  Icons.zoom_out,
	color:  Colors.deepOrange,
	title:  Text("Center Motion Toast"),
	description:  Text("Another motion toast example"),
	position:  MotionToastPosition.center
).show(context);

  • Using onClose parameter (display two successive toasts)
MotionToast.success(
	title:  Text("User Data"),
	description:  Text("Your data has been deleted"),
	onClose: (){
		MotionToast.error(
			title:  Text("User Data"),
			description:  Text("Your data has been deleted"),
		).show(context);
	},
).show(context);

  • Two-Colors Motion Toast

MotionToast(
	icon:  Icons.zoom_out,
	primaryColor:  Colors.orange[500]!,
	secondaryColor:  Colors.grey,
	backgroundType:  BackgroundType.solid,
	title:  Text('Two Color Motion Toast'),
	description:  Text('Another motion toast example'),
	position:  MotionToastPosition.top,
	animationType:  AnimationType.fromTop,
	height:  100,
	width:  300,
).show(context);

  • Transparent background motion toast

MotionToast(
	icon:  Icons.zoom_out,
	primaryColor:  Colors.grey[400]!,
	secondaryColor:  Colors.yellow,
	backgroundType:  BackgroundType.transparent,
	title:  Text('Two Color Motion Toast'),
	description:  Text('Another motion toast example'),
	position:  MotionToastPosition.center,
	height:  100,
	width:  300,
).show(context);

  • Motion toast without sidebar and with border

MotionToast(
	icon:  Icons.zoom_out,
	primaryColor:  Colors.orange[500]!,
	secondaryColor:  Colors.grey,
	backgroundType:  BackgroundType.solid,
	title:  Text('Two Color Motion Toast'),
	description:  Text('Another motion toast example'),
	displayBorder: true,
	displaySideBar: false,
).show(context);

  • Dismiss the toast from your UI screen

MotionToast toast = MotionToast(
	icon:  Icons.zoom_out,
	primaryColor:  Colors.orange[500]!,
	secondaryColor:  Colors.grey,
	backgroundType:  BackgroundType.solid,
	title:  Text('Two Color Motion Toast'),
	description:  Text('Another motion toast example'),
	displayBorder: true,
	displaySideBar: false,
).show(context);
toast.dismiss();

Contribution

Of course the project is open source, and you can contribute to it repository link

If you found a bug, open an issue.

If you have a feature request, open an issue.

If you want to contribute, submit a pull request.

Contributors

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add motion_toast

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  motion_toast: ^2.6.7

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:motion_toast/motion_toast.dart';

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:motion_toast/motion_toast.dart';
import 'package:motion_toast/resources/arrays.dart';

void main() {
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Motion Toast Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: SizedBox(
            width: double.infinity,
            child: SingleChildScrollView(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  const Text(
                    'Motion Toast Examples',
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
                  ),
                  const SizedBox(
                    height: 15,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displaySuccessMotionToast();
                      },
                      child: const Text('Success Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayWarningMotionToast();
                      },
                      child: const Text('Warning Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayErrorMotionToast();
                      },
                      child: const Text('Error Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayInfoMotionToast();
                      },
                      child: const Text('Info Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayDeleteMotionToast();
                      },
                      child: const Text('Delete Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayResponsiveMotionToast();
                      },
                      child: const Text('Responsive Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayCustomMotionToast();
                      },
                      child: const Text('Custom Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayMotionToastWithoutSideBar();
                      },
                      child: const Text('Without sidebar'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayMotionToastWithBorder();
                      },
                      child: const Text('With border'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayTwoColorsMotionToast();
                      },
                      child: const Text('Two-color Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displayTransparentMotionToast();
                      },
                      child: const Text('Transparent Motion Toast'),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    width: 200,
                    child: ElevatedButton(
                      onPressed: () {
                        _displaySimultaneouslyToasts();
                      },
                      child: const Text('Simultaneously taosts'),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  void _displaySuccessMotionToast() {
    MotionToast toast = MotionToast.success(
      title: const Text(
        'Lorum Ipsum',
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
      description: const Text(
        'Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor, sed do eiusmod tempor, sed do eiusmod tempor',
        style: TextStyle(fontSize: 12),
      ),
      layoutOrientation: ToastOrientation.rtl,
      animationType: AnimationType.fromRight,
      dismissable: true,
    );
    toast.show(context);
    Future.delayed(const Duration(seconds: 4)).then((value) {
      toast.dismiss();
    });
  }

  void _displayWarningMotionToast() {
    MotionToast.warning(
      title: const Text(
        'Warning Motion Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('This is a Warning'),
      animationCurve: Curves.bounceIn,
      borderRadius: 0,
      animationDuration: const Duration(milliseconds: 1000),
    ).show(context);
  }

  void _displayErrorMotionToast() {
    MotionToast.error(
      title: const Text(
        'Error',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('Please enter your name'),
      position: MotionToastPosition.top,
      barrierColor: Colors.black.withOpacity(0.3),
      width: 300,
      height: 80,
      dismissable: false,
    ).show(context);
  }

  void _displayInfoMotionToast() {
    MotionToast.info(
      title: const Text(
        'Info Motion Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      position: MotionToastPosition.center,
      description: const Text('Example of Info Toast'),
    ).show(context);
  }

  void _displayDeleteMotionToast() {
    MotionToast.delete(
      title: const Text(
        'Deleted',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('The item is deleted'),
      animationType: AnimationType.fromTop,
      position: MotionToastPosition.top,
    ).show(context);
  }

  void _displayResponsiveMotionToast() {
    MotionToast(
      icon: Icons.rocket_launch,
      primaryColor: Colors.purple,
      title: const Text(
        'Custom Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text(
        'Hello my name is Flutter dev',
      ),
    ).show(context);
  }

  void _displayCustomMotionToast() {
    MotionToast(
      primaryColor: Colors.pink,
      title: const Text(
        'Bugatti',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      dismissable: false,
      description: const Text(
        'Automobiles Ettore Bugatti was a German then French manufacturer of high-performance automobiles. The company was founded in 1909 in the then-German city of Molsheim, Alsace, by the Italian-born industrial designer Ettore Bugatti. ',
      ),
    ).show(context);
  }

  void _displayMotionToastWithoutSideBar() {
    MotionToast(
      icon: Icons.zoom_out,
      primaryColor: Colors.orange[500]!,
      secondaryColor: Colors.grey,
      backgroundType: BackgroundType.solid,
      title: const Text('Two Color Motion Toast'),
      description: const Text('Another motion toast example'),
      displayBorder: true,
      displaySideBar: false,
    ).show(context);
  }

  void _displayMotionToastWithBorder() {
    MotionToast(
      icon: Icons.zoom_out,
      primaryColor: Colors.deepOrange,
      title: const Text('Top Motion Toast'),
      description: const Text('Another motion toast example'),
      position: MotionToastPosition.top,
      animationType: AnimationType.fromTop,
      displayBorder: true,
      width: 350,
      height: 100,
      padding: const EdgeInsets.only(
        top: 30,
      ),
    ).show(context);
  }

  void _displayTwoColorsMotionToast() {
    MotionToast(
      icon: Icons.zoom_out,
      primaryColor: Colors.orange[500]!,
      secondaryColor: Colors.grey,
      backgroundType: BackgroundType.solid,
      title: const Text(
        'Two Color Motion Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('Another motion toast example'),
      position: MotionToastPosition.top,
      animationType: AnimationType.fromTop,
      width: 350,
      height: 100,
    ).show(context);
  }

  void _displayTransparentMotionToast() {
    MotionToast(
      icon: Icons.zoom_out,
      primaryColor: Colors.grey[400]!,
      secondaryColor: Colors.yellow,
      backgroundType: BackgroundType.transparent,
      title: const Text(
        'Two Color Motion Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('Another motion toast example'),
      position: MotionToastPosition.center,
      width: 350,
      height: 100,
    ).show(context);
  }

  void _displaySimultaneouslyToasts() {
    MotionToast.warning(
      title: const Text(
        'Warning Motion Toast',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('This is a Warning'),
      animationCurve: Curves.bounceIn,
      borderRadius: 0,
      animationDuration: const Duration(milliseconds: 1000),
    ).show(context);
    MotionToast.error(
      title: const Text(
        'Error',
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
      ),
      description: const Text('Please enter your name'),
      animationType: AnimationType.fromLeft,
      position: MotionToastPosition.top,
      width: 300,
      height: 80,
    ).show(context);
  }
}

Download Details:

Author: koukibadr

Source Code: https://github.com/koukibadr/Motion-Toast

#flutter #animation #motion #toast 

A Beautiful Designed toast with animations for Flutter
Royce  Reinger

Royce Reinger

1679029140

Towr: Trajectory Optimizer for Walking Robots

Towr

A light-weight and extensible C++ library for trajectory optimization for legged robots.

A base-set of variables, costs and constraints that can be combined and extended to formulate trajectory optimization problems for legged systems. These implementations have been used to generate a variety of motions such as monoped hopping, biped walking, or a complete quadruped trotting cycle, while optimizing over the gait and step durations in less than 100ms (paper).

Features:
✔️ Intuitive and efficient formulation of variables, cost and constraints using Eigen.
✔️ ifopt enables using the high-performance solvers Ipopt and Snopt.
✔️ Elegant rviz visualization of motion plans using xpp.
✔️ ROS/catkin integration (optional).
✔️ Light-weight (~6k lines of code) makes it easy to use and extend.

Install

The easiest way to install is through the ROS binaries:

sudo apt-get install ros-<ros-distro>-towr-ros

In case these don't yet exist for your distro, there are two ways to build this code from source:

  • Option 1: core library and hopper-example with pure CMake.
  • Option 2 (recommended): core library & GUI & ROS-rviz-visualization built with catkin and ROS.

Building with CMake

Install dependencies CMake, Eigen, Ipopt:

Install ifopt, by cloning the repo and then: cmake .. && make install on your system.

sudo apt-get install cmake libeigen3-dev coinor-libipopt-dev

Build towr:

git clone https://github.com/ethz-adrl/towr.git && cd towr/towr
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make
sudo make install # copies files in this folder to /usr/local/*
# sudo xargs rm < install_manifest.txt # in case you want to uninstall the above

Test (hopper_example.cc): Generates a motion for a one-legged hopper using Ipopt

./towr-example # or ./towr-test if gtest was found

Use: You can easily customize and add your own constraints and variables to the optimization problem. Herefore, add the following to your CMakeLists.txt:

find_package(towr 1.2 REQUIRED)
add_executable(main main.cpp) # Your custom variables, costs and constraints added to TOWR
target_link_libraries(main PUBLIC towr::towr) # adds include directories and libraries

Building with catkin

We provide a ROS-wrapper for the pure cmake towr library, which adds a keyboard interface to modify goal state and motion types as well as visualizes the produces motions plans in rviz using xpp.

Install dependencies CMake, catkin, Eigen, Ipopt, ROS, xpp, ncurses, xterm:

sudo apt-get install cmake libeigen3-dev coinor-libipopt-dev libncurses5-dev xterm
sudo apt-get install ros-<ros-distro>-desktop-full ros-<ros-distro>-xpp

Build workspace:

cd catkin_workspace/src
git clone https://github.com/ethz-adrl/ifopt.git
git clone https://github.com/ethz-adrl/towr.git
cd ..
catkin_make_isolated -DCMAKE_BUILD_TYPE=Release # or `catkin build`
source ./devel_isolated/setup.bash

Use: Include in your catkin project by adding to your CMakeLists.txt

Add the following to your package.xml:

<package>
  <depend>towr</depend>
</package>
add_compile_options(-std=c++11)
find_package(catkin COMPONENTS towr) 
include_directories(${catkin_INCLUDE_DIRS})
target_link_libraries(foo ${catkin_LIBRARIES})

Run

Launch the program using

roslaunch towr_ros towr_ros.launch  # debug:=true  (to debug with gdb)

Click in the xterm terminal and hit 'o'.

Information about how to tune the paramters can be found here.

Develop

Library overview

  • The relevant classes and parameters to build on are collected modules.
  • A nice graphical overview as UML can be seen here.
  • The doxygen documentation provides helpful information for developers.

Problem formulation

  • This code formulates the variables, costs and constraints using ifopt, so it makes sense to briefly familiarize with the syntax using this example.
  • A minimal towr example without ROS, formulating a problem for a one-legged hopper, can be seen here and is great starting point.
  • We recommend using the ROS infrastructure provided to dynamically visualize, plot and change the problem formulation. To define your own problem using this infrastructure, use this example as a guide.

Add your own variables, costs and constraints

  • This library provides a set of variables, costs and constraints to formulate the trajectory optimization problem. An example formulation of how to combine these is given, however, this formulation can probably be improved. To add your own e.g. constraint-set, define a class with it's values and derivatives, and then add it to the formulation nlp.AddConstraintSet(your_custom_constraints); as shown here.

Add your own robot

  • Want to add your own robot to towr? Start here.
  • To visualize that robot in rviz, see xpp.

Contribute

We love pull request, whether its new constraint formulations, additional robot models, bug fixes, unit tests or updating the documentation. Please have a look at CONTRIBUTING.md for more information.
See here the list of contributors who participated in this project.

Projects using towr

Publications

All publications underlying this code can be found here. The core paper is:

@article{winkler18,
  author    = {Winkler, Alexander W and Bellicoso, Dario C and 
               Hutter, Marco and Buchli, Jonas},
  title     = {Gait and Trajectory Optimization for Legged Systems 
               through Phase-based End-Effector Parameterization},
  journal   = {IEEE Robotics and Automation Letters (RA-L)},
  year      = {2018},
  month     = {July},
  pages     = {1560-1567},
  volume    = {3},
  doi       = {10.1109/LRA.2018.2798285},
}

A broader overview of the topic of Trajectory optimization and derivation of the Single-Rigid-Body Dynamics model used in this work: DOI 10.3929/ethz-b-000272432


Download Details:

Author: Ethz-adrl
Source Code: https://github.com/ethz-adrl/towr 
License: BSD-3-Clause license

#machinelearning #cpluplus #robots #compute #motion #planning 

Towr: Trajectory Optimizer for Walking Robots
Royce  Reinger

Royce Reinger

1679021160

Toppra: Robotic Motion Planning Library

toppra: Time-Optimal Path Parameterization

Overview

toppra is a library for computing the time-optimal path parametrization for robots subject to kinematic and dynamic constraints. In general, given the inputs:

  1. a geometric path p(s), s in [0, s_end];
  2. a list of constraints on joint velocity, joint accelerations, tool Cartesian velocity, et cetera.

toppra returns the time-optimal path parameterization: s_dot (s), from which the fastest trajectory q(t) that satisfies the given constraints can be found.

Documentation and tutorials are available here.

You can install the package with pip:

pip install toppra

To install from source for development:

pip install -r requirement3.txt
pip install -e .

Support

Bug tracking

Please report any issues, questions or feature request via Github issues tracker.

Have a quick question? Try asking in our slack channel.

Contributions

Pull Requests are welcome! Create a Pull Request and we will review your proposal!

Credits

toppra was originally developed by Hung Pham (Eureka Robotics, former CRI Group) and Phạm Quang Cưong (Eureka Robotics, CRI Group) with major contributions from talented contributors:

If you have taken part in developing and supporting the library, feel free to add your name to the list.

The development is also generously supported by Eureka Robotics.

Citing toppra

If you use this library for your research, we encourage you to

  1. reference the accompanying paper A new approach to Time-Optimal Path Parameterization based on Reachability Analysis, IEEE Transactions on Robotics, vol. 34(3), pp. 645-659, 2018.
  2. put a star on this repository.

Download Details:

Author: Hungpham2511
Source Code: https://github.com/hungpham2511/toppra 
License: MIT license

#machinelearning #python #robotics #motion #planning #algorithms 

Toppra: Robotic Motion Planning Library
Royce  Reinger

Royce Reinger

1679017260

Ruckig: Motion Generation for Robots and Machines

Ruckig

Instantaneous Motion Generation for Robots and Machines.

Ruckig generates trajectories on-the-fly, allowing robots and machines to react instantaneously to sensor input. Ruckig calculates a trajectory to a target waypoint (with position, velocity, and acceleration) starting from any initial state limited by velocity, acceleration, and jerk constraints. Besides the target state, Ruckig allows to define intermediate positions for waypoint following. For state-to-state motions, Ruckig guarantees a time-optimal solution. With intermediate waypoints, Ruckig calculates the path and its time parametrization jointly, resulting in significantly faster trajectories compared to traditional methods.

More information can be found at ruckig.com and in the corresponding paper Jerk-limited Real-time Trajectory Generation with Arbitrary Target States, accepted for the Robotics: Science and Systems (RSS), 2021 conference.

Installation

Ruckig has no dependencies (except for testing). To build Ruckig using CMake, just run

mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make

To install Ruckig in a system-wide directory, use (sudo) make install. An example of using Ruckig in your CMake project is given by examples/CMakeLists.txt. However, you can also include Ruckig as a directory within your project and call add_subdirectory(ruckig) in your parent CMakeLists.txt. To enable the Online API for intermediate waypoints, just pass the BUILD_ONLINE_CLIENT flag to CMake.

Ruckig is also available as a Python module, in particular for development or debugging purposes. The Ruckig Community Version can be installed from PyPI via

pip install ruckig

When using CMake, the Python module can be built using the BUILD_PYTHON_MODULE flag. If you're only interested in the Python module (and not in the C++ library), you can build and install Ruckig via pip install ..

Tutorial

Furthermore, we will explain the basics to get started with online generated trajectories within your application. There is also a collection of examples that guide you through the most important features of Ruckig. A time-optimal trajectory for a single degree of freedom is shown in the figure below. We also added plots for the resulting trajectories of all examples. Let's get started!

Trajectory Profile

Waypoint-based Trajectory Generation

Ruckig provides three main interface classes: the Ruckig, the InputParameter, and the OutputParameter class.

First, you'll need to create a Ruckig instance with the number of DoFs as a template parameter, and the control cycle (e.g. in seconds) in the constructor.

Ruckig<6> ruckig {0.001}; // Number DoFs; control cycle in [s]

The input type has 3 blocks of data: the current state, the target state and the corresponding kinematic limits.

InputParameter<6> input; // Number DoFs
input.current_position = {0.2, ...};
input.current_velocity = {0.1, ...};
input.current_acceleration = {0.1, ...};
input.target_position = {0.5, ...};
input.target_velocity = {-0.1, ...};
input.target_acceleration = {0.2, ...};
input.max_velocity = {0.4, ...};
input.max_acceleration = {1.0, ...};
input.max_jerk = {4.0, ...};

OutputParameter<6> output; // Number DoFs

Given all input and output resources, we can iterate over the trajectory at each discrete time step. For most applications, this loop must run within a real-time thread and controls the actual hardware.

while (ruckig.update(input, output) == Result::Working) {
  // Make use of the new state here!
  // e.g. robot->setJointPositions(output.new_position);

  output.pass_to_input(input); // Don't forget this!
}

Within the control loop, you need to update the current state of the input parameter according to the calculated trajectory. Therefore, the pass_to_input method copies the new kinematic state of the output to the current kinematic state of the input parameter. If (in the next step) the current state is not the expected, pre-calculated trajectory, Ruckig will calculate a new trajectory based on the novel input. When the trajectory has reached the target state, the update function will return Result::Finished.

Intermediate Waypoints

The Ruckig Community Version now supports intermediate waypoints via a remote API. Make sure to include -DBUILD_ONLINE_CLIENT=ON as a CMake flag when compiling - the PyPI Python version should bring that out of the box. To allocate the necessary memory for a variable number of waypoints beforehand, we need to pass the maximum number of waypoints to Ruckig via

Ruckig<6> otg {0.001, 8};
InputParameter<6> input {8};
OutputParameter<6> output {8};

The InputParameter class takes the number of waypoints as an optional input, however usually you will fill in the values (and therefore reserve its memory) yourself. Then you're ready to set intermediate via points by

input.intermediate_positions = {
  {0.2, ...},
  {0.8, ...},
};

As soon as at least one intermediate positions is given, the Ruckig Community Version switches to the mentioned (of course, non real-time capable) remote API. If you require real-time calculation on your own hardware, please contact us for the Ruckig Pro Version.

When using intermediate positions, both the underlying motion planning problem as well as its calculation changes significantly. In particular, there are some fundamental limitations for jerk-limited online trajectory generation regarding the usage of waypoints. Please find more information about these limitations here, and in general we recommend to use

input.intermediate_positions = otg.filter_intermediate_positions(input.intermediate_positions, {0.1, ...});

to filter waypoints according to a (high) threshold distance. Setting interrupt_calculation_duration makes sure to be real-time capable by refining the solution in the next control invocation. Note that this is a soft interruption of the calculation. Currently, no minimum or discrete durations are supported when using intermediate positions.

Input Parameter

To go into more detail, the InputParameter type has following members:

using Vector = std::array<double, DOFs>; // By default

Vector current_position;
Vector current_velocity; // Initialized to zero
Vector current_acceleration; // Initialized to zero

std::vector<Vector> intermediate_positions; // (only in Pro Version)

Vector target_position;
Vector target_velocity; // Initialized to zero
Vector target_acceleration; // Initialized to zero

Vector max_velocity;
Vector max_acceleration;
Vector max_jerk;

std::optional<Vector> min_velocity; // If not given, the negative maximum velocity will be used.
std::optional<Vector> min_acceleration; // If not given, the negative maximum acceleration will be used.

std::optional<Vector> min_position; // (only in Pro Version)
std::optional<Vector> max_position; // (only in Pro Version)

std::array<bool, DOFs> enabled; // Initialized to true
std::optional<double> minimum_duration;
std::optional<double> interrupt_calculation_duration; // [µs], (only in Pro Version)

ControlInterface control_interface; // The default position interface controls the full kinematic state.
Synchronization synchronization; // Synchronization behavior of multiple DoFs
DurationDiscretization duration_discretization; // Whether the duration should be a discrete multiple of the control cycle (off by default)

std::optional<Vector<ControlInterface>> per_dof_control_interface; // Sets the control interface for each DoF individually, overwrites global control_interface
std::optional<Vector<Synchronization>> per_dof_synchronization; // Sets the synchronization for each DoF individually, overwrites global synchronization

On top of the current state, target state, and constraints, Ruckig allows for a few more advanced settings:

  • A minimum velocity and acceleration can be specified - these should be a negative number. If they are not given, the negative maximum velocity or acceleration will be used (similar to the jerk limit). For example, this might be useful in human robot collaboration settings with a different velocity limit towards a human. Or, when switching between different moving coordinate frames like picking from a conveyer belt.
  • You can overwrite the global kinematic limits to specify limits for each section between two waypoints separately by using e.g. per_section_max_velocity.
  • If a DoF is not enabled, it will be ignored in the calculation. Ruckig will output a trajectory with constant acceleration for those DoFs.
  • A minimum duration can be optionally given. Note that Ruckig can not guarantee an exact, but only a minimum duration of the trajectory.
  • The control interface (position or velocity control) can be switched easily. For example, a stop trajectory or visual servoing can be easily implemented with the velocity interface.
  • Different synchronization behaviors (i.a. phase, time, or no synchonization) are implemented. Phase synchronization results in straight-line motions.
  • The trajectory duration might be constrained to a multiple of the control cycle. This way, the exact state can be reached at a control loop execution.

We refer to the API documentation of the enumerations within the ruckig namespace for all available options.

Input Validation

To check that Ruckig is able to generate a trajectory before the actual calculation step,

ruckig.validate_input(input, check_current_state_within_limits=false, check_target_state_within_limits=true);
// returns boolean

returns false if an input is not valid. The two boolean arguments check that the current or target state are within the limits. The check includes a typical catch of jerk-limited trajectory generation: When the current state is at maximal velocity, any positive acceleration will inevitable lead to a velocity violation at a future timestep. In general, this condition is fulfilled when

Abs(acceleration) <= Sqrt(2 * max_jerk * (max_velocity - Abs(velocity))).

If both arguments are set to true, the calculated trajectory is guaranteed to be within the kinematic limits throughout its duration. Also, note that there are range constraints of the input due to numerical reasons, see below for more details.

Result Type

The update function of the Ruckig class returns a Result type that indicates the current state of the algorithm. This can either be working, finished if the trajectory has finished, or an error type if something went wrong during calculation. The result type can be compared as a standard integer.

StateError Code
Working0
Finished1
Error-1
ErrorInvalidInput-100
ErrorTrajectoryDuration-101
ErrorPositionalLimits-102
ErrorExecutionTimeCalculation-110
ErrorSynchronizationCalculation-111

Output Parameter

The output class includes the new kinematic state and the overall trajectory.

Vector new_position;
Vector new_velocity;
Vector new_acceleration;

Trajectory trajectory; // The current trajectory
double time; // The current, auto-incremented time. Reset to 0 at a new calculation.

size_t new_section; // Index of the section between two (possibly filtered) intermediate positions.
bool did_section_change; // Was a new section reached in the last cycle?

bool new_calculation; // Whether a new calculation was performed in the last cycle
bool was_calculation_interrupted; // Was the trajectory calculation interrupted? (only in Pro Version)
double calculation_duration; // Duration of the calculation in the last cycle [µs]

Moreover, the trajectory class has a range of useful parameters and methods.

double duration; // Duration of the trajectory
std::array<double, DOFs> independent_min_durations; // Time-optimal profile for each independent DoF

<...> at_time(double time); // Get the kinematic state of the trajectory at a given time
<...> get_position_extrema(); // Returns information about the position extrema and their times

Again, we refer to the API documentation for the exact signatures.

Offline Calculation

Ruckig also supports an offline approach for calculating a trajectory:

result = ruckig.calculate(input, trajectory);

When only using this method, the Ruckig constructor does not need a control cycle (delta_time) as an argument. However if given, Ruckig supports stepping through the trajectory with

while (ruckig.update(trajectory, output) == Result::Working) {
  // Make use of the new state here!
  // e.g. robot->setJointPositions(output.new_position);
}

starting from the current output.time (currently Ruckig Pro only).

Tracking Interface

When following an arbitrary signal with position, velocity, acceleration, and jerk-limitation, the straight forward way would be to pass the current state to Ruckig's target state. However, as the resulting trajectory will take time to catch up, this approach will always lag behind the signal. The tracking interface solves this problem by predicting ahead (e.g. with constant acceleration by default) and is therefore able to follow signals very closely in a time-optimal way. This might be very helpful for (general) tracking, robot servoing, or trajectory post-processing applications.

To use the tracking interface, construct

Trackig<1> otg {0.01};  // control cycle

and set the current state as well as the kinematic constraints via

input.current_position = {0.0};
input.current_velocity = {0.0};
input.current_acceleration = {0.0};
input.max_velocity = {0.8};
input.max_acceleration = {2.0};
input.max_jerk = {5.0};

Then, we can track a signal in an online manner within the real-time control loop

for (double t = 0; t < 10.0; t += otg.delta_time) {
  auto target_state = signal(t); // signal returns position, velocity, and acceleration
  auto res = otg.update(target_state, input, output);
  // Make use of the smooth target motion here (e.g. output.new_position)

  output.pass_to_input(input);
}

Please find a complete example here. This functionality can also be used in an offline manner, e.g. when the entire signal is known beforehand. Here, we call the

smooth_trajectory = otg.calculate_trajectory(target_states, input);

method with the trajectory given as a std::vector of target states. The Tracking interface is available in the Ruckig Pro version.

Dynamic Number of Degrees of Freedom

So far, we have told Ruckig the number of DoFs as a template parameter. If you don't know the number of DoFs at compile-time, you can set the template parameter to ruckig::DynamicDOFs and pass the DoFs to the constructor:

Ruckig<DynamicDOFs> otg {6, 0.001};
InputParameter<DynamicDOFs> input {6};
OutputParameter<DynamicDOFs> output {6};

However, we recommend to keep the template parameter when possible: First, it has a performance benefit of a few percent. Second, it is convenient for real-time programming due to its easier handling of memory allocations. When using dynamic degrees of freedom, make sure to allocate the memory of all vectors beforehand.

Custom Vector Types

Ruckig supports custom vector types to make interfacing with your code even easier and more flexible. Most importantly, you can switch to Eigen Vectors simply by including Eigen (3.4 or later) before Ruckig

#include <Eigen/Core> // Version 3.4 or later
#include <ruckig/ruckig.hpp>

and then call the constructors with the ruckig::EigenVector parameter.

Ruckig<6, EigenVector> otg {0.001};
InputParameter<6, EigenVector> input;
OutputParameter<6, EigenVector> output;

Now every in- and output of Ruckig's API (such as current_position, new_position or max_jerk) are Eigen types! To define completely custom vector types, you can pass a C++ template template parameter to the constructor. This template template parameter needs to fulfill a range of template arguments and methods:

template<class Type, size_t DOFs>
struct MinimalVector {
  Type operator[](size_t i) const; // Array [] getter
  Type& operator[](size_t i); // Array [] setter
  size_t size() const; // Current size
  bool operator==(const MinimalVector<T, DOFs>& rhs) const; // Equal comparison operator

  // Only required in combination with DynamicDOFs, e.g. to allocate memory
  void resize(size_t size);
};

Note that DynamicDOFs corresponds to DOFs = 0. We've included a range of examples for using Ruckig with (10) Eigen, (11) custom vector types, and (12) custom types with a dynamic number of DoFs.

Tests and Numerical Stability

The current test suite validates over 5.000.000.000 random trajectories as well as many additional edge cases. The numerical exactness is tested for the final position and final velocity to be within 1e-8, for the final acceleration to be within 1e-10, and for the velocity, acceleration and jerk limit to be within of a numerical error of 1e-12. These are absolute values - we suggest to scale your input so that these correspond to your required precision of the system. For example, for most real-world systems we suggest to use input values in [m] (instead of e.g. [mm]), as 1e-8m is sufficient precise for practical trajectory generation. Furthermore, all kinematic limits should be below 1e12. The maximal supported trajectory duration is 7e3, and you can scale your input parameter to avoid that limitation. Note that Ruckig will also output values outside of this range, there is however no guarantee for correctness.

Benchmark

We find that Ruckig is more than twice as fast as Reflexxes Type IV for state-to-state motions and well-suited for control cycles as low as 250 microseconds. The Ruckig Community Version is in general a more powerful and open-source alternative to the Reflexxes Type IV library. In fact, Ruckig is the first Type V trajectory generator for arbitrary target states and even supports directional velocity and acceleration limits, while also being faster on top.

Benchmark

For trajectories with intermediate waypoints, we compare Ruckig to Toppra, a state-of-the-art library for robotic motion planning. Ruckig is able to improve the trajectory duration on average by around 10%, as the path planning and time parametrization are calculated jointly. Moreover, Ruckig is real-time capable and supports jerk-constraints.

Benchmark

Development

Ruckig is written in C++17. It is continuously tested on ubuntu-latest, macos-latest, and windows-latest against following versions

  • Doctest v2.4 (only for testing)
  • Pybind11 v2.9 (only for python wrapper)

If you still need to use C++11, you can patch the Ruckig Community Version by calling bash scripts/patch-c++11.sh. Note that this will result in a performance drop of a few percent. Moreover, the Python module is not supported.

Used By

Ruckig is used by over hundred research labs, companies, and open-source projects worldwide, including:

Citation

@article{berscheid2021jerk,
  title={Jerk-limited Real-time Trajectory Generation with Arbitrary Target States},
  author={Berscheid, Lars and Kr{\"o}ger, Torsten},
  journal={Robotics: Science and Systems XVII},
  year={2021}
}

Download Details:

Author: pantor
Source Code: https://github.com/pantor/ruckig 
License: MIT license

#machinelearning #cpluplus #robotics #motion #planning 

Ruckig: Motion Generation for Robots and Machines
Royce  Reinger

Royce Reinger

1679009160

OMPL: The Open Motion Planning Library (OMPL)

The Open Motion Planning Library (OMPL)

Linux / macOS - Windows 

Visit the OMPL installation page for detailed installation instructions.

OMPL has the following required dependencies:

  • Boost (version 1.58 or higher)
  • CMake (version 3.5 or higher)
  • Eigen (version 3.3 or higher)

The following dependencies are optional:

Once dependencies are installed, you can build OMPL on Linux, macOS, and MS Windows. Go to the top-level directory of OMPL and type the following commands:

mkdir -p build/Release
cd build/Release
cmake ../..
# next step is optional
make -j 4 update_bindings # if you want Python bindings
make -j 4 # replace "4" with the number of cores on your machine

Download Details:

Author: ompl
Source Code: https://github.com/ompl/ompl 
License: View license

#machinelearning #cpluplus #robotics #motion #planning 

OMPL: The Open Motion Planning Library (OMPL)
Royce  Reinger

Royce Reinger

1678993440

An Optimal Control Library for Robot Control Under Contact Sequence

Introduction

Crocoddyl is an optimal control library for robot control under contact sequence. Its solvers are based on novel and efficient Differential Dynamic Programming (DDP) algorithms. Crocoddyl computes optimal trajectories along with optimal feedback gains. It uses Pinocchio for fast computation of robots dynamics and their analytical derivatives.

If you want to follow the current developments, you can directly refer to the devel branch. If you want to directly dive into Crocoddyl, only one single line is sufficient

conda install crocoddyl -c conda-forge

and if you prefer pip (in Python 3 or 2):

pip install --user crocoddyl

Installation

Crocoddyl can be easily installed on various Linux (Ubuntu, Fedora, etc.) and Unix distributions (Mac OS X, BSD, etc.).

Crocoddyl features

Crocoddyl is versatible:

  • various optimal control solvers (DDP, FDDP, BoxDDP, etc) - single and multi-shooting methods
  • analytical and sparse derivatives via Pinocchio
  • Euclidian and non-Euclidian geometry friendly via Pinocchio
  • handle autonomous and nonautomous dynamical systems
  • numerical differentiation support
  • automatic differentiation support via CppAD

Crocoddyl is efficient and flexible:

  • cache friendly,
  • multi-thread friendly
  • Python bindings (including models and solvers abstractions) via Boost Python
  • C++ 14/17/20 compliant
  • extensively tested
  • automatic code generation support via CppADCodeGen

Installation through robotpkg

You can install this package through robotpkg. robotpkg is a package manager tailored for robotics softwares. It greatly simplifies the release of new versions along with the management of their dependencies. You just need to add the robotpkg apt repository to your sources.list and then use sudo apt install robotpkg-py27-crocoddyl (or py3X for python 3.X, depending on your system):

If you have never added robotpkg as a softwares repository, please follow first the instructions from 1 to 3; otherwise, go directly to instruction 4. Those instructions are similar to the installation procedures presented in http://robotpkg.openrobots.org/debian.html.

  • Add robotpkg as source repository to apt:
sudo tee /etc/apt/sources.list.d/robotpkg.list <<EOF
deb [arch=amd64] http://robotpkg.openrobots.org/wip/packages/debian/pub $(lsb_release -sc) robotpkg
deb [arch=amd64] http://robotpkg.openrobots.org/packages/debian/pub $(lsb_release -sc) robotpkg
EOF
  • Register the authentication certificate of robotpkg:
curl http://robotpkg.openrobots.org/packages/debian/robotpkg.key | sudo apt-key add -
  • You need to run at least once apt update to fetch the package descriptions:
sudo apt-get update
  • The installation of Crocoddyl:
sudo apt install robotpkg-py36-crocoddyl # for Python 3

sudo apt install robotpkg-py27-crocoddyl # for Python 2

Finally you will need to configure your environment variables, e.g.:

export PATH=/opt/openrobots/bin:$PATH
export PKG_CONFIG_PATH=/opt/openrobots/lib/pkgconfig:$PKG_CONFIG_PATH
export LD_LIBRARY_PATH=/opt/openrobots/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/openrobots/lib/python2.7/site-packages:$PYTHONPATH

Building from source

Crocoddyl is c++ library with Python bindings for versatile and fast prototyping. It has the following dependencies:

You can run examples, unit-tests and benchmarks from your build dir:

cd build
make test
make -s examples-quadrupedal_gaits INPUT="display plot" # enable display and plot
make -s benchmarks-cpp-quadrupedal_gaits INPUT="100 walk" # number of trials ; type of gait

Alternatively, you can see the 3D result and/or graphs of your run examples (through gepetto-viewer and matplotlib), you can use

export CROCODDYL_DISPLAY=1
export CROCODDYL_PLOT=1

After installation, you could run the examples as follows:

python -m crocoddyl.examples.quadrupedal_gaits "display" "plot" # enable display and plot

If you want to learn about Crocoddyl, take a look at the Jupyter notebooks. Start in the following order.

Documentation

The documentation of Crocoddyl of its last release is available here.

Citing Crocoddyl

To cite Crocoddyl in your academic research, please use the following bibtex lines:

@inproceedings{mastalli20crocoddyl,
  author={Mastalli, Carlos and Budhiraja, Rohan and Merkt, Wolfgang and Saurel, Guilhem and Hammoud, Bilal
  and Naveau, Maximilien and Carpentier, Justin and Righetti, Ludovic and Vijayakumar, Sethu and Mansard, Nicolas},
  title={{Crocoddyl: An Efficient and Versatile Framework for Multi-Contact Optimal Control}},
  booktitle = {IEEE International Conference on Robotics and Automation (ICRA)},
  year={2020}
}

and the following one to reference this website:

@misc{crocoddylweb,
   author = {Carlos Mastalli, Rohan Budhiraja and Nicolas Mansard and others},
   title = {Crocoddyl: a fast and flexible optimal control library for robot control under contact sequence},
   howpublished = {https://github.com/loco-3d/crocoddyl/wikis/home},
   year = {2019}
}

Crocoddyl contributions go beyond efficient software implementation as well. Please also consider to cite the algorithm contributions of our different solvers and formulations:

  • Feasibility-driven DDP (FDDP): [1]
  • Control-limited feasibility-driven DDP (Box-FDDP): [2]
  • Multi-phase rigid optimal control: [3]

Finally, please also consider citing Pinocchio, which contributes to the efficient implementation of rigid body algorithms and their derivatives. For more details how to cite Pinocchio visit: https://github.com/stack-of-tasks/pinocchio.

Below, there is list of the selected publications that describe different components of Crocoddyl. For a complete list see PUBLICATIONS.md.

Selected publications

[1] C. Mastalli, R. Budhiraja, W. Merkt, G. Saurel, B. Hammoud, M. Naveau, J. Carpentier, L. Righetti, S. Vijayakumar and N. Mansard. Crocoddyl: An Efficient and Versatile Framework for Multi-Contact Optimal Control, IEEE International Conference on Robotics and Automation (ICRA), 2020

[2] C. Mastalli, W. Merkt, J. Marti-Saumell, H. Ferrolho, J. Sola, N. Mansard, S. Vijayakumar. A Direct-Indirect Hybridization Approach to Control-Limited DDP, 2021

[3] R. Budhiraja, J. Carpentier, C. Mastalli and N. Mansard. Differential Dynamic Programming for Multi-Phase Rigid Contact Dynamics, IEEE RAS International Conference on Humanoid Robots (ICHR), 2018

Questions and Issues

You have a question or an issue? You may either directly open a new issue or use the mailing list crocoddyl@laas.fr.

Steering Committee

Crocoddyl is being managed by a steering committee which meets every two weeks to discuss the ongoing developments.

The committee is being led by Carlos Mastalli (University of Edinburgh) and Rohan Budhiraja (LAAS-CNRS). Nicolas Mansard (LAAS-CNRS), Guilhem Saurel (LAAS-CNRS) and Justin Carpentier (INRIA) are other members of the committee.

Credits

The following people have been involved in the development of Crocoddyl:

Acknowledgments

The development of Crocoddyl is supported by the EU MEMMO project, and the EU RoboCom++ project. It is maintained by the Gepetto team @LAAS-CNRS, the Statistical Machine Learning and Motor Control Group @University of Edinburgh, and the Willow team @INRIA.


Download Details:

Author: loco-3d
Source Code: https://github.com/loco-3d/crocoddyl 
License: BSD-3-Clause license

#machinelearning #cpluplus #robotics #motion #planning

An Optimal Control Library for Robot Control Under Contact Sequence
Nat  Grady

Nat Grady

1676354520

Animate A React Application with Framer Motion

Animate A React Application with Framer Motion

Animations on web pages involve moving elements on the screen to improve the visual experience of users. These animations are visually appealing and tend to draw users’ attention to buttons, images, and other important information. Overall, it contributes to establishing a solid connection between users and the content on the screen.

In the past, web pages were very plain and lacked interactivity because they were only intended to display information, and there was no capability to create appealing visual experiences. Things have changed dramatically in recent years, thanks to the availability of libraries and packages that make it easier to animate and add visual experiences to your web pages.

This article will teach you how to use the Framer Motion library to animate a React application. Why should you use Framer Motion? And how it works by animating a mini-project.

What is Framer Motion?

Framer Motion is an open-source production-ready motion library for React. It allows you to add all forms of animations and transitions directly to Document Object Model (DOM) elements defined in your React components. Its syntax is easy to understand, and with a few lines of code, you will be able to implement awesome animations.

Framer Motion uses an awesome API that gives you access to the motion component. You can plug this component into your React DOM elements giving you access to additional props for animation. For example, the div element will become motion.div.

The Framer Motion also has beginner-friendly documentation with lots of practical examples and illustrations showing how to perform simple to complex forms of animations and transitions.

How Framer Motion works

Framer Motion uses the motion component, which you can attach to any DOM element to implement an animation or transition effect. 

<motion.div>
    <p> An animated text </p>
</motion.div>

Code language: HTML, XML (xml)

Nothing changes when you attach the motion component to your element. Instead, it supercharges that element with animation capabilities, giving you access to props, keys, and values you can use to add any animation. For example, you can access the animate prop, which takes in a dynamic value — an object which contains the different properties and values you want to animate.

<motion.div animate={{x: -10, y: 10}}>
    <p> An animated text </p>
</motion.div>

Code language: HTML, XML (xml)

The above animation will cause the div element to slide 10px to the left and then 10px to the bottom when it loads from the original position specified in style. 

ℹ️ When units are not specified, calculations are done in pixels. You can also specify your preferred units by attaching them. For example: animate={{x:"-10rem"}}.

Getting started with Framer Motion in React

Framer Motion is a popular library with over 1.6 million weekly downloads. You can install the library into your React project using the command below in your terminal:

$ npm i framer-motion

Once you have installed it, you can verify if it has been installed in your package.json file’s dependencies object:

"dependencies": {
    // ...
    "framer-motion": "^7.5.3",
    "react": "^18.2.0",
    // ...
},

Code language: JSON / JSON with Comments (json)

Once you have installed the Framer Motion library, you can import the motion component into a component you wish to use within your project, and everything will work fine.

import { motion } from 'framer-motion';

<motion.h1 animate={{x: 10, y: 20}}>
    An animated text
</motion.h1>

Code language: JavaScript (javascript)

Animating elements in React

The motion component can be applied to any DOM element within your React component. You can apply it to the container elements, headings, text elements, images, and other elements. This motion component gives you access to props like animate, which you can use to adjust the color, size, position, display, and add other animation effects to the DOM element.

<motion.div
    animate={{
        x: 10,
        backgroundColor: '#fff',
        boxShadow: '10px 10px 0 rgba(0, 0, 0, 0.2)',
    }}
>
    <h1>Hi</h1>
    <img src={myImage} alt="" />
</motion.div>

Code language: HTML, XML (xml)

In the example above, the background color changes to white. A box shadow is added to the div when it loads, and the elements contained in the div moves 10px to the right.

It is also important to know that you can apply any form of animation based on CSS attributes. For example, you use x, y, and z to move elements similar to translateX, translateY, and translateZ

You can also scale the size of an element using the scale attribute for both x and y or scaleX and scaleY if you wish to apply separate values. Example:

<motion.div animate={{ scale: 0.8 }} >
    <h1>Hi</h1>
    <motion.img animate={{ scaleX: 1.2 }} src={myImage} alt="" />
</motion.div>

Code language: HTML, XML (xml)

The same applies to transformation values like skew and rotate. It’s also important to mention that it supports all forms of value types, such as numbers, strings, and colors in Hex, RGB, and HSLA as strings. You can also calculate values using the calc() function.

<motion.img animate={{ x: "calc(100vw - 50%)" }} src={myImage} alt="" />

Code language: HTML, XML (xml)

Setting initial animation state

At this point, you have only used the animate prop, which makes you animate elements from the default CSS style to your specified values. But this is not always what you want; sometimes, you want to specify where your animation starts and ends. For example, you might want your text to slide from the left of your screen to the middle.

You can specify initial animation values using the initial props, which work similarly to the animate prop and uses similar attributes and values.

<motion.div
    initial={{ opacity: 0, x: '-100vh' }}
    animate={{ opacity: 1, x: 0 }}
>
    <h1>Hi</h1>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt
        perspiciatis voluptates nihil dolores eum architecto eligendi
    </p>
</motion.div>

Code language: HTML, XML (xml)

How to add transition options to animation

You will notice that these animations happen fast to the extent that you might not see them unless you pay close attention. 

The page animates a block of Lorem ipsum text by indenting it and reverting it to its original position.

 

You can fix this by adding transition effects using the transition prop. This transition prop defines the type of animation used when animating between two values and how these values animate from one state to another.

For example, if you add a duration of 1, the animation will run for 1 second.

<motion.div
    initial={{ opacity: 0, x: '-100vh' }}
    animate={{ opacity: 1, x: 0 }}
    transition={{ duration: 1 }}
>
    <h1>Hi</h1>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt
        perspiciatis voluptates nihil dolores eum architecto eligendi
    </p>
</motion.div>

Code language: HTML, XML (xml)The page animates a block of Lorem ipsum text for a second by indenting it and reverting it to its original position.

There are three major transition types, and they all have their specific effect; they include Tween, Spring, or Inertia. Tween is the default type for all animation, so if you want a spring form of animation, you will need to specify the transition type as Spring

<motion.div
    initial={{ opacity: 0, x: '-100vh' }}
    animate={{ opacity: 1, x: 0 }}
    transition={{ type: 'spring', duration: 1 }}
>
    <h1>Hi</h1>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt
        perspiciatis voluptates nihil dolores eum architecto eligendi
    </p>
</motion.div>

Code language: HTML, XML (xml)

Each type has some attributes peculiar to them. For example, when you use the transition type of spring, you have access to an attribute like bounce which specifies how elastic the spring effect is on the element.

<motion.div
    initial={{ opacity: 0, x: '-100vh' }}
    animate={{ opacity: 1, x: 0 }}
    transition={{ type: 'spring', bounce: 0.6 }}
>
    <h1>Hi</h1>
    <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt
        perspiciatis voluptates nihil dolores eum architecto eligendi
    </p>
</motion.div>

Code language: HTML, XML (xml)Spring animation.

There are other attributes like delay, which you can use to set a delay time before the animation renders.

How to use keyframes and repeat animation in Framer Motion

Sometimes, you may want your elements to animate through several different animation values, which may be from left to right, depending on what you want. In CSS, this is handled with keyframes, but for Framer Motion, you can do this with a square bracket holding as many values as you want.

<motion.button
    animate={{ x: [0, -20, 20, -20, 20, 0] }}
    transition={{ delay: 1 }}
>
    My Button
</motion.button>

The page animates a button to the left after a second from the initial render.

Note that in the example above, the animation waited for 1 second before moving the button to the left 20px and right 20px twice before returning to its original position. This can be applied to any animation transform attribute such as x, y, scale, rotate and others.

<motion.button
    animate={{ scale: [1, 1.2, 1, 1.2, 1] }}
    transition={{ delay: 1 }}
>
    My Button
</motion.button>

Code language: HTML, XML (xml)

You will notice that these animations stop after it has completed the number of times specified. The example above will start at 1, which is the default. It will then scale up and down twice to its default value.

However, you may want the animation effect to repeat by using the transition property yoyo and set its value to Infinity or the number of times you wish your animation repeats.

💡 The transition property yoyo lets you specify the number of times you want an animation to repeat.

<motion.button
    animate={{ scale: 1.2 }}
    transition={{ delay: 1, yoyo: Infinity }}
>
    My Button
</motion.button>

Code language: HTML, XML (xml)

In the code block above, you will notice you no longer need the square bracket. All you need is the value it should change to when it leaves the default, 1.

The page animates a Generate Quote button once the button is hovered on.

Implement hover animation gestures

You often want to apply hover gestures to buttons, cards, and other elements to draw the user’s attention. You might want a button to scale up and down when a user hovers over the button instead of just scaling up and down without any action from the user. To do this, you can use the whileHover prop, which works similarly to previous props.

<motion.button
    whileHover={{
        scale: 1.2,
        transition: { yoyo: Infinity },
    }}
>
    My Button
</motion.button>

Code language: HTML, XML (xml)

ℹ️ The transition property for whileHover prop is placed within the curly braces and not outside the whileHover prop.

The page animation transitions once the Generate Quote button is hovered on.

Variants: A better way to use Framer Motion in React

At this point, you have learned the basics of Framer Motion, how it works and how you could use it to implement animations directly on your DOM elements. You must have started asking yourself why you should add all animation properties and values directly on each element because it tends to make your code clumsy and not easy to understand.

This is where variants come in. You use variants to remove the props object and place them outside your component, so you only use the object names within your DOM element. This also helps you use the same animation effect for multiple elements within your component to avoid repetition.

import { Link } from 'react-router-dom';
import logo from './../images/logo.svg';
import { motion } from 'framer-motion';

const headerVariants = {
    initial: {
        y: '-100vh',
    },
    animate: {
        y: 0,
        transition: {
            delay: 0.5,
            duration: 0.5,
            type: 'spring',
        },
    },
};

const Header = () => {
    return (
        <div className="container">
            <motion.div
                className="header"
                variants={headerVariants}
                initial="initial"
                animate="animate"
            >
                <Link to="/">
                    <img src={logo} alt="" />
                </Link>
                <h1>Quotes Circle</h1>
            </motion.div>
        </div>
    );
};

export default Header;

Code language: JavaScript (javascript)

In the code block above, an object (variant) is created to hold all the animation properties and values. This object contained two child objects, one to hold the initial animation and the second to hold the final animation (animate). You can give them any name:

const headerVariants = {
    initial: {
        y: '-100vh',
    },
    animate: {
        y: 0,
        transition: {
            delay: 0.5,
            duration: 0.5,
            type: 'spring',
        },
    },
};

Code language: JavaScript (javascript)

To make use of this variant in your React DOM elements, then you will use the variants prop and pass the variant name into it. Also, you will assign the initial and animate prop with the name you used when creating your variant, but this time as a string and not a dynamic value.

<motion.div
    variants={headerVariants}
    initial="initial"
    animate="animate"
>
    <Link to="/">
        <img src={logo} alt="" />
    </Link>
    <h1>Quotes Circle</h1>
</motion.div>

Code language: HTML, XML (xml)

You can have as many variants as possible, and if you use the same initial and animate value, you would not need to declare that for children elements in your component.

const headerVariants = {
    initial: {
        y: '-100vh',
    },
    animate: {
        y: 0,
        transition: {
            delay: 0.5,
            duration: 0.5,
            type: 'spring',
        },
    },
};

const logoVariants = {
    initial: {
        x: '-100vw',
    },
    animate: {
        x: 0,
        transition: {
            delay: 1,
        },
    },
};

const Header = () => {
    return (
        <div className="container">
            <motion.div
                className="header"
                variants={headerVariants}
                initial="initial"
                animate="animate"
            >
                <Link to="/">
                    <motion.img src={logo} variants={logoVariants} />
                </Link>
                <h1>Quotes Circle</h1>
            </motion.div>
        </div>
    );
};

Code language: JavaScript (javascript)

If you look at the logo image element, you will notice the variants prop was only defined. There is no need to define the initial and animate prop because it has the same name as the previous one you already declared in the parent element.

How to animate routes in React with Framer Motion

When building applications that have more than one page, you will want to add animation between each page. These animations may not be conspicuous but can add a nice experience rather than having content suddenly leave the screen.

The page animates a new component once the route changes.

The GIF above almost looks like the routes are animated, but you will notice that it only animates in but not out. This means that the components disappear when they unmount, so you will want to add an animation instead.

This is done with the AnimatePresence component, which notifies components when they will be unmounted and allows them to defer that unmounting until after the animation is complete. This animation is added with the exit prop to your component’s parent element.

To implement this, you will first import AnimatePresence component to the App.js file where you configured your routes or if it’s in the index.js file. Once that is done, you will wrap the Routes component with the AnimatePresence component:

import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import QuotesPage from './pages/QuotesPage';
import Header from './components/Header';
import { AnimatePresence } from 'framer-motion';

const App = () => {

    return (
    <>
        <Header />
        <AnimatePresence>
        <Routes location={location} key={location.key}>
            <Route path="/" element={<Home />} />
            <Route path="/quote" element={<QuotesPage />} />
        </Routes>
        </AnimatePresence>
    </>
    );
};

export default App;

Code language: JavaScript (javascript)

Then you will need to use useLocation router hook to know when the route changes. This will be attached to the Route component:

import { Routes, Route, useLocation } from 'react-router-dom';
import Home from './pages/Home';
import QuotesPage from './pages/QuotesPage';
import Header from './components/Header';
import { AnimatePresence } from 'framer-motion';

const App = () => {
    const location = useLocation();

    return (
    <>
        <Header />
        <AnimatePresence>
        <Routes location={location} key={location.key}>
            <Route path="/" element={<Home />} />
            <Route path="/quote" element={<QuotesPage />} />
        </Routes>
        </AnimatePresence>
    </>
    );
};

export default App;

Code language: JavaScript (javascript)

At this point, you can now add exit animation to all your component’s parent elements, and the exit animation will work very fine.

For example, if you want to add it to the Home component, which is a route as seen above. You can use variants or add the animation object directly to the exit prop.

// ...
import { motion } from 'framer-motion';

const Home = () => {
    // ...

    const containerVariants = {
        hidden: {
            opacity: 0,
            x: '100vw',
        },
        visible: {
            opacity: 1,
            x: 0,
            transition: {
                type: 'spring',
                mass: 0.4,
                damping: 8,
                when: 'beforeChildren',
                staggerChildren: 0.4,
            },
        },
        exit: {
            x: '-100vw',
            transition: {
                ease: 'easeInOut',
            },
        },
    };

    return (
        <motion.div
            className="container"
            variants={containerVariants}
            initial="hidden"
            animate="visible"
            exit="exit"
        >
            { // ... component elements }
        </motion.div>
    );
};

export default Home;

Code language: JavaScript (javascript)

At this point, your routes will be animated when any component leaves the screen. It will animate out by sliding to the left as specified in the exit object:

exit: {
    x: '-100vw',
    transition: {
        ease: 'easeInOut',
    },
},

Code language: JavaScript (javascript)

But you will notice that the animation of the new component already happens when the previous component leaves the screen. You can fix this by adding an exitBeforeEnter prop to the <AnimatePresence> component you used to wrap the App.js component.

// ... imports
const App = () => {
    const location = useLocation();
    return (
    <>
        <Header />
        <AnimatePresence exitBeforeEnter>
        { // ... routes }
        </AnimatePresence>
    </>
    );
};

export default App;

Code language: JavaScript (javascript)Each page is animated once the route is changed.

How to animate SVGs with Framer Motion

Framer Motion allows you to animate your Scalable Vector Graphics (SVGs) via their path (A way of drawing your SVGs). This is possible by attaching the motion component to the path element of your SVG and then adding your preferred animation alongside the pathlength property with a value of 0 and 1 for when the animation starts and when it ends.

Suppose you have an SVG, you will notice that these SVGs usually have a path or paths defined with so many attributes and values:

const AnimateSVG = () => {
    return (
        <div className="container">
            <svg
                className="my-svg"
                viewBox="0 0 256 256"
                xmlns="http://www.w3.org/2000/svg"
            >
                <rect fill="none" height="256" width="256" />
                <path
                    d="M108,144H40a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                />
                <path
                    d="M224,144H156a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                />
            </svg>
        </div>
    );
};

export default AnimateSVG;

Code language: JavaScript (javascript)

You can attach the motion component to the path element and then use the initial and animate props to add animation to the path:

import { motion } from 'framer-motion';

const AnimateSVG = () => {
    return (
        <div className="container">
            <svg
                className="my-svg"
                viewBox="0 0 256 256"
                xmlns="http://www.w3.org/2000/svg"
            >
                <rect fill="none" height="256" width="256" />
                <motion.path
                    d="M108,144H40a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                    initial={{ pathLength: 0 }}
                    animate={{ pathLength: 1 }}
                    transition={{ duration: 2 }}
                />
                <motion.path
                    d="M224,144H156a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                    initial={{ pathLength: 0 }}
                    animate={{ pathLength: 1 }}
                    transition={{ duration: 2 }}
                />
            </svg>
        </div>
    );
};

export default AnimateSVG;

Code language: JavaScript (javascript)

In the code block above, you will notice that pathLength is used to add animation to the SVG. The initial animation is set to 0, meaning nothing shows, and then within 2 seconds, the SVG will draw.

Animated SVG.

Instead of adding the animation directly, you can use variants and add that single variant to both paths. You can also add more forms of animation, such as opacity if you wish.

import { motion } from 'framer-motion';

const AnimateSVG = () => {
    const pathVariants = {
        hidden: {
            opacity: 0,
            pathLength: 0,
        },
        visible: {
            opacity: 1,
            pathLength: 1,
            transition: {
                duration: 2,
                ease: 'easeInOut',
            },
        },
    };

    return (
        <div className="container">
            <motion.svg
                className="my-svg"
                viewBox="0 0 256 256"
                xmlns="http://www.w3.org/2000/svg"
            >
                <rect fill="none" height="256" width="256" />
                <motion.path
                    d="M108,144H40a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                    variants={pathVariants}
                    initial="hidden"
                    animate="visible"
                />
                <motion.path
                    d="M224,144H156a8,8,0,0,1-8-8V72a8,8,0,0,1,8-8h60a8,8,0,0,1,8,8v88a40,40,0,0,1-40,40"
                    fill="none"
                    stroke="#000"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="12"
                    variants={pathVariants}
                    initial="hidden"
                    animate="visible"
                />
            </motion.svg>
        </div>
    );
};

export default AnimateSVG;

Code language: JavaScript (javascript)

Run the sandbox to preview the application in action:

ta-da 🎉!

In this guide, you have learned how to use Framer Motion to add animation to your React application elements, routes, and SVGs. It is important to note that the Framer Motion offers more than what has been covered in this guide, with many more animation options.

This guide has laid a proper foundation to help you navigate through and use the library in your React application for the first time. You can now check out the Framer Motion documentation to understand more options and animate your React application better. You can also get the animated demo project from this article’s GitHub repository.

Have fun coding!

I’m Joel Olawanle, a frontend developer and technical writer interested in making the web accessible to everyone by always looking for ways to give back to the tech community. Follow me and connect with me on Twitter.

Original article source at: https://coderpad.io

#react #application #motion 

Animate A React Application with Framer Motion
Bongani  Ngema

Bongani Ngema

1675331520

Pokedex Demonstrates Modern Android Development with Hilt

Pokedex

🗡️ Pokedex demonstrates modern Android development with Hilt, Coroutines, Flow, Jetpack (Room, ViewModel), and Material Design based on MVVM architecture.

Download

Go to the Releases to download the latest APK.

preview.gif

Tech stack & Open-source libraries

  • Minimum SDK level 21
  • Kotlin based, Coroutines + Flow for asynchronous.
  • Jetpack
    • Lifecycle: Observe Android lifecycles and handle UI states upon the lifecycle changes.
    • ViewModel: Manages UI-related data holder and lifecycle aware. Allows data to survive configuration changes such as screen rotations.
    • DataBinding: Binds UI components in your layouts to data sources in your app using a declarative format rather than programmatically.
    • Room: Constructs Database by providing an abstraction layer over SQLite to allow fluent database access.
    • Hilt: for dependency injection.
  • Architecture
    • MVVM Architecture (View - DataBinding - ViewModel - Model)
    • Bindables: Android DataBinding kit for notifying data changes to UI layers.
    • Repository Pattern
  • Retrofit2 & OkHttp3: Construct the REST APIs and paging network data.
  • Sandwich: Construct a lightweight and modern response interface to handle network payload for Android.
  • Moshi: A modern JSON library for Kotlin and Java.
  • WhatIf: Check nullable objects and empty collections more fluently.
  • Bundler: Android Intent & Bundle extensions, which insert and retrieve values elegantly.
  • ksp: Kotlin Symbol Processing API.
  • Turbine: A small testing library for kotlinx.coroutines Flow.
  • Material-Components: Material design components for building ripple animation, and CardView.
  • Glide, GlidePalette: Loading images from network.
  • TransformationLayout: Implementing transformation motion animations.
  • Custom Views
    • Rainbow: An easy way to apply gradations and tinting for Android.
    • AndroidRibbon: A simple way to implement a beautiful ribbon with the shimmering on Android.
    • ProgressView: A polished and flexible ProgressView, fully customizable with animations.
  • Timber: A logger with a small, extensible API.

Architecture

Pokedex is based on the MVVM architecture and the Repository pattern, which follows the Google's official architecture guidance.

architecture

The overall architecture of Pokedex is composed of two layers; the UI layer and the data layer. Each layer has dedicated components and they have each different responsibilities, as defined below:

Pokedex was built with Guide to app architecture, so it would be a great sample to show how the architecture works in real-world projects.

Architecture Overview

architecture

  • Each layer follows unidirectional event/data flow; the UI layer emits user events to the data layer, and the data layer exposes data as a stream to other layers.
  • The data layer is designed to work independently from other layers and must be pure, which means it doesn't have any dependencies on the other layers.

With this loosely coupled architecture, you can increase the reusability of components and scalability of your app.

UI Layer

architecture

The UI layer consists of UI elements to configure screens that could interact with users and ViewModel that holds app states and restores data when configuration changes.

  • UI elements observe the data flow via DataBinding, which is the most essential part of the MVVM architecture.
  • With Bindables, which is an Android DataBinding kit for notifying data changes, you can implement two-way binding, and data observation in XML very clean.

Data Layer

architecture

The data Layer consists of repositories, which include business logic, such as querying data from the local database and requesting remote data from the network. It is implemented as an offline-first source of business logic and follows the single source of truth principle.
 

Pokedex is an offline-first app is an app that is able to perform all, or a critical subset of its core functionality without access to the internet. So users don't need to be up-to-date on the network resources every time and it will decrease users' data consumption. For further information, you can check out Build an offline-first app.

Modularization

architecture

Pokedex adopted modularization strategies below:

  • Reusability: Modulizing reusable codes properly enable opportunities for code sharing and limits code accessibility in other modules at the same time.
  • Parallel Building: Each module can be run in parallel and it reduces the build time.
  • Strict visibility control: Modules restrict to expose dedicated components and access to other layers, so it prevents they're being used outside the module
  • Decentralized focusing: Each developer team can assign their dedicated module and they can focus on their own modules.

For more information, check out the Guide to Android app modularization.

MAD Score

summary kotlin

Open API

Pokedex using the PokeAPI for constructing RESTful API.
PokeAPI provides a RESTful API interface to highly detailed objects built from thousands of lines of data related to Pokémon.

Find this repository useful? ❤️

Support it by joining stargazers for this repository. :star: 
Also, follow me on GitHub for my next creations! 🤩

Download Details:

Author: Skydoves
Source Code: https://github.com/skydoves/Pokedex 
License: Apache-2.0 license

#kotlin #android #pokemon #motion 

Pokedex Demonstrates Modern Android Development with Hilt

Create a Floating Contact Section with Divi Scroll Motion Effects

Every website needs a contact section, but that doesn’t mean you need to go for a standard design. With Divi’s scroll effects, you can create a floating contact section that will stand out. Improve your user interaction with a vertical scrolling contact section layout that will invite visitors to engage with your contact form. In this post, we’ll show you how to create a full width floating contact section that you can add to any page. You could even add it at the top of a site-wide footer with the Divi Theme Builder.

Below, you’ll find a free downloadable folder with the JSON layout to upload to your own Divi Library. We’ve also included a PSD template to help you recreate the map background, plus an SVG of the map pin so you can personalize it with your own colors.

#divi #motion #effects

Create a Floating Contact Section with Divi Scroll Motion Effects

How to Use Transformed Motion Shapes as Backgrounds with Divi

Divi’s new scroll effects are made for you to easily take your web design experience to the next level. Of course, you can apply it to elements within your section directly, but you can choose to add motion to underlying elements too. Going for an underlying approach allows you to keep content static while having background motion going on. In this tutorial, we’ll use transformed motion shapes as our underlying elements to create an animated section. We’ll handle two different examples but the possibilities are truly endless. You’ll be able to download the JSON file for free as well!

#divi #motion #backgrounds

How to Use Transformed Motion Shapes as Backgrounds with Divi
Teresa  Jerde

Teresa Jerde

1596950927

Adding animations to your Android application using the Lottie library

Adding animations to your android app makes it more fun and interesting as compared to static text or pictures. The easiest way to do that is using a 3rd party library Lottie by airbnb.

The best part is you can use animations without having to write a single line of code.

For brevity, we will use ready made animations available on lottiefiles.com. Alternatively you can also build your own custom animations using Adobe after effects and use them in your app. (See it in action here)

Let’s begin 🏁

Let’s start by downloading all the animation files you need for your project from LottieFiles. For this guide, I’ll use a total of three animation files for

Splash Screen

This is shown for a brief 2 seconds when user opens the app.

#lottie #motion #android #kotlin #animatin

Adding animations to your Android application using the Lottie library