Using custom curve in Flutter Hero animations
Tags: flutter, hero, dart, animations
Published: 2019-09-24 05:16:34

---
title: Using custom curve in Flutter Hero animations
published: true
tags: flutter, hero, dart, animations
canonical_url: 
---

Sometimes the default Hero behavior is not enough and you’d like to add some custom taste to it. One of the simple ways to do it is to customize curve of the transition animation.

In this post you’ll see a sample that allows to use any custom curve to animate bounds of the Hero. In my case it was a bit faster expansion in vertical axis.

![Comparison](https://roszkowski.dev/images/hero.gif)

**Contents**

- Hero properties
- What is createRectTween
- How to change the default implementation

# Hero properties

[Hero](https://api.flutter.dev/flutter/widgets/Hero-class.html) class has several convenient properties that allow to customize its behavior. These are:

- `flightShuttleBuilder` that allows to wrap or change entire Hero animation by e.g. adding rotation or fade transition
- `placeholderBuilder` that gives us possibility to show Widget in place previously occupied by the animated widget
- `createRectTween` which is a function that determines the bounds of the Hero during animation - that’s what we want to customize today

# What is createRectTween

This property takes a `CreateRectTween` function which is simply a typedef for `Tween<Rect> Function(Rect begin, Rect end)`.

It means that it interpolates two Rects between `begin` and `end` state. By default a `RectTween(begin: begin, end: end)` is used in Hero. It uses its [lerp](https://api.flutter.dev/flutter/dart-ui/Rect/lerp.html) method which aside from few asserts only interpolates Rect coordinates in linear manner:

```dart
static Rect lerp(Rect a, Rect b, double t) {
  assert(t != null);
  if (a == null && b == null)
    return null;
  if (a == null)
    return Rect.fromLTRB(b.left * t, b.top * t, b.right * t, b.bottom * t);
  if (b == null) {
    final double k = 1.0 - t;
    return Rect.fromLTRB(a.left * k, a.top * k, a.right * k, a.bottom * k);
  }
  return Rect.fromLTRB(
    lerpDouble(a.left, b.left, t),
    lerpDouble(a.top, b.top, t),
    lerpDouble(a.right, b.right, t),
    lerpDouble(a.bottom, b.bottom, t),
  );
}

```

The method `lerpDouble` is where the interpolation takes place:

```dart
double lerpDouble(num a, num b, double t) {
    if (a == null && b == null) return null;
    a ??= 0.0;
    b ??= 0.0;
    return a + (b - a) * t;
}

```

# How to change the default implementation

When defining your Hero you should return a custom `createRectTween` function like this:

```dart
Hero(
    tag: index,
    createRectTween: (begin, end) {
        return CustomRectTween(a: begin, b: end);
    },
    child: Poster(),
),

```

And finally `CustomRectTween` has to extend `RectTween` and to have overwritten `lerp` method.

The parameter `t` is animation clock value between 0.0 and 1.0. Each `Curve` can be used to interpolate any given value between 0.0 and 1.0 on the curve. I use my custom cubic curve in this example.

```dart
class CustomRectTween extends RectTween {
  CustomRectTween({this.a, this.b}) : super(begin: a, end: b);
  final Rect a;
  final Rect b;

  @override
  Rect lerp(double t) {
    Curves.elasticOut.transform(t);
    //any curve can be applied here e.g. Curve.elasticOut.transform(t);
    final verticalDist = Cubic(0.72, 0.15, 0.5, 1.23).transform(t);

    final top = lerpDouble(a.top, b.top, t) * (1 - verticalDist);
    return Rect.fromLTRB(
      lerpDouble(a.left, b.left, t),
      top,
      lerpDouble(a.right, b.right, t),
      lerpDouble(a.bottom, b.bottom, t),
    );
  }

  double lerpDouble(num a, num b, double t) {
    if (a == null && b == null) return null;
    a ??= 0.0;
    b ??= 0.0;
    return a + (b - a) * t;
  }
}

```

It’s important to note that I wanted to change only `top` coordinate of the Hero’s Rect, so when calculating the value I use `(1 - verticalDist)` (thus inverting the curve).

I hope you’ll find it useful and try to experiment with Hero widget on your own.

I highly recommend the post [Mastering Hero Animations in Flutter](https://medium.com/flutter-community/mastering-hero-animations-in-flutter-bc07e1bea327) by Chema Molins from Flutter Community.