Skip to content

Instantly share code, notes, and snippets.

@onetdev
Created November 16, 2019 22:37
Show Gist options
  • Select an option

  • Save onetdev/20d9da1aac63b8a08fdbaaece80f8629 to your computer and use it in GitHub Desktop.

Select an option

Save onetdev/20d9da1aac63b8a08fdbaaece80f8629 to your computer and use it in GitHub Desktop.

Revisions

  1. onetdev created this gist Nov 16, 2019.
    47 changes: 47 additions & 0 deletions circular_reveal_clipper.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    import 'dart:math' show sqrt, max;
    import 'dart:ui' show lerpDouble;

    import 'package:flutter/material.dart';

    @immutable
    class CircularRevealClipper extends CustomClipper<Path> {
    final double fraction;
    final Alignment centerAlignment;
    final Offset centerOffset;
    final double minRadius;
    final double maxRadius;

    CircularRevealClipper({
    @required this.fraction,
    this.centerAlignment,
    this.centerOffset,
    this.minRadius,
    this.maxRadius,
    });

    @override
    Path getClip(Size size) {
    final Offset center = this.centerAlignment?.alongSize(size) ??
    this.centerOffset ??
    Offset(size.width / 2, size.height / 2);
    final minRadius = this.minRadius ?? 0;
    final maxRadius = this.maxRadius ?? calcMaxRadius(size, center);

    return Path()
    ..addOval(
    Rect.fromCircle(
    center: center,
    radius: lerpDouble(minRadius, maxRadius, fraction),
    ),
    );
    }

    @override
    bool shouldReclip(CustomClipper<Path> oldClipper) => true;

    static double calcMaxRadius(Size size, Offset center) {
    final w = max(center.dx, size.width - center.dx);
    final h = max(center.dy, size.height - center.dy);
    return sqrt(w * w + h * h);
    }
    }
    57 changes: 57 additions & 0 deletions reveal_route.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    import 'package:flutter/material.dart';
    /// Since the clipper is not exported from circular_reveal_animation package
    /// You will need to get that separately.
    import 'circular_reveal_clipper.dart';

    class RevealRoute extends PageRouteBuilder {
    final Widget page;
    final AlignmentGeometry centerAlignment;
    final Offset centerOffset;
    final double minRadius;
    final double maxRadius;

    /// Reveals the next item pushed to the navigation using circle shape.
    ///
    /// You can provide [centerAlignment] for the reveal center or if you want a
    /// more precise use only [centerOffset] and leave other blank.
    ///
    /// The transition doesn't affect the entry screen so we will only touch
    /// the target screen.
    RevealRoute({
    @required this.page,
    this.minRadius = 0,
    @required this.maxRadius,
    this.centerAlignment,
    this.centerOffset,
    }) : assert(centerOffset != null || centerAlignment != null),
    super(
    /// We could override pageBuilder but it's a required parameter of
    /// [PageRouteBuilder] and it won't build unless it's provided.
    pageBuilder: (
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    ) {
    return page;
    },
    );

    @override
    Widget buildTransitions(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
    ) {
    return ClipPath(
    clipper: CircularRevealClipper(
    fraction: animation.value,
    centerAlignment: centerAlignment,
    centerOffset: centerOffset,
    minRadius: minRadius,
    maxRadius: maxRadius,
    ),
    child: child,
    );
    }
    }