Giter VIP home page Giter VIP logo

Comments (3)

andre-ab avatar andre-ab commented on July 20, 2024 2

If you wanted to leave it as default, just make a few changes:

If you don't want the animation to drag the widget to the cart, null safety is in both methods
createAddToCartAnimation
If you want the animation to be according to the quantity that will be added to the cart
createAnimationByQty

class AddToCartAnimation


final Function(Future<void> Function(GlobalKey))? createAddToCartAnimation;

  /// It's the same principle as [createAddToCartAnimation] the only difference
  /// is that the animation  will be multiplied according to the amount passed.
  final Function(Future<void> Function(GlobalKey, int))? createAnimationByQty;

null safety check

  
    @override
  void initState() {
    if (this.widget.createAddToCartAnimation != null) {
      this.widget.createAddToCartAnimation!(runAddToCartAnimation);
    }

    if (this.widget.createAnimationByQty != null) {
      this.widget.createAnimationByQty!(animationByQty);
    }
    super.initState();
  }
  

// Method to make animation according to quantity

   Future<void> animationByQty(GlobalKey widgetKey, int qty) async {
    for (var i = 0; i < qty; i++) {
      runAddToCartAnimation(widgetKey);
      await Future.delayed(const Duration(milliseconds: 200));
    }
  }

end of changes in class addToCartAnimation

Call

//  Start the variable in the controller or class MyHomePageState extends State<MyHomePage>

late Function(GlobalKey, int) animationByQty;


 // @override
 // Widget build(BuildContext context)

return AddToCartAnimation(
      // To send the library the location of the Cart icon
      cartKey: controller.cartKey,
      height: 30,
      width: 30,
      opacity: 0.85,
      dragAnimation: const DragToCartAnimationOptions(rotation: true),
      jumpAnimation: const JumpAnimationOptions(),
      
      createAnimationByQty: (animationByQty) {
        controller.animationByQty = animationByQty;
      },

Method that does the magic, can be in the controller or on the same page


  Future<void> listClick(GlobalKey widgetKey, int quant) async {
    await animationByQty(widgetKey, quant);
    cartTotalItems += quant;
    await cartKey.currentState!.runCartAnimation((cartTotalItems).toString());
  }





Full code StatefulWidget

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  // We can detect the location of the cart by this  GlobalKey<CartIconKey>
  GlobalKey<CartIconKey> cartKey = GlobalKey<CartIconKey>();
  // late Function(GlobalKey) runAddToCartAnimation;

  late Function(GlobalKey, int) animationByQty;
  var _cartQuantityItems = 0;

  @override
  Widget build(BuildContext context) {
    return AddToCartAnimation(
      // To send the library the location of the Cart icon
      cartKey: cartKey,
      height: 30,
      width: 30,
      opacity: 0.85,
      dragAnimation: const DragToCartAnimationOptions(
        rotation: true,
      ),
      jumpAnimation: const JumpAnimationOptions(),
      createAnimationByQty: (animationByQty) {
        animationByQty = animationByQty;
      },
      /*  createAddToCartAnimation: (runAddToCartAnimation) {
        // You can run the animation by addToCartAnimationMethod, just pass trough the the global key of  the image as parameter
        this.runAddToCartAnimation = runAddToCartAnimation;
      }, */
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          centerTitle: false,
          actions: [
            //  Adding 'clear-cart-button'
            IconButton(
              icon: const Icon(Icons.cleaning_services),
              onPressed: () {
                _cartQuantityItems = 0;
                cartKey.currentState!.runClearCartAnimation();
              },
            ),
            const SizedBox(width: 16),
            AddToCartIcon(
              key: cartKey,
              icon: const Icon(Icons.shopping_cart),
              badgeOptions: const BadgeOptions(
                active: true,
                backgroundColor: Colors.red,
              ),
            ),
            const SizedBox(
              width: 16,
            )
          ],
        ),
        body: ListView(
          children: List.generate(
            15,
            (index) => AppListItem(
              onClick: listClick,
              index: index,
            ),
          ),
        ),
      ),
    );
  }

  Future<void> listClick(GlobalKey widgetKey, int quant) async {
    await animationByQty(widgetKey, quant);
    _cartQuantityItems += quant;
    await cartKey.currentState!
        .runCartAnimation((_cartQuantityItems).toString());
  }
  /*  
   void listClick(GlobalKey widgetKey) async {
    await runAddToCartAnimation(widgetKey);
    await cartKey.currentState!
        .runCartAnimation((++_cartQuantityItems).toString());
  }
 */
}

Full code Class AddToCartAnimation


import 'dart:math';

import 'drag_to_cart_animation_options.dart';

import 'jump_animation_options.dart';
import 'add_to_cart_icon.dart';
import 'globalkeyext.dart';
import 'package:flutter/material.dart';

export 'add_to_cart_icon.dart';
export 'jump_animation_options.dart';
export 'drag_to_cart_animation_options.dart';

class _PositionedAnimationModel {
  bool showAnimation = false;
  bool animationActive = false;
  Offset imageSourcePoint = Offset.zero;
  Offset imageDestPoint = Offset.zero;
  Size imageSourceSize = Size.zero;
  Size imageDestSize = Size.zero;
  bool rotation = false;
  double opacity = 0.85;
  late Container container;
  Duration duration = Duration.zero;
  Curve curve = Curves.easeIn;
}

/// An add to cart animation which provide you an animation by sliding the product to cart in the Flutter app
class AddToCartAnimation extends StatefulWidget {
  final Widget child;

  /// The Global Key of the [AddToCartIcon] element. We need it because we need to know where is the cart icon is located in the screen. Based on the location, we are dragging given widget to the cart.
  final GlobalKey<CartIconKey> cartKey;

  /// you can receive [runAddToCartAnimation] animation method on [createAddToCartAnimation].
  /// [runAddToCartAnimation] animation method runs the add to cart animation based on the given parameters.
  /// Add to cart animation drags the given widget to the cart based on their location via global keys
  final Function(Future<void> Function(GlobalKey))? createAddToCartAnimation;

  /// It's the same principle as [createAddToCartAnimation] the only difference
  /// is that the animation  will be multiplied according to the amount passed.
  final Function(Future<void> Function(GlobalKey, int))? createAnimationByQty;

  /// What Should the given widget's height while dragging to the cart
  final double height;

  /// What Should the given widget's width while dragging to the cart
  final double width;

  /// What Should the given widget's opacity while dragging to the cart
  final double opacity;

  /// Should the given widget jump before the dragging
  final JumpAnimationOptions jumpAnimation;

  /// The animation options while given widget sliding to cart
  final DragToCartAnimationOptions dragAnimation;

  const AddToCartAnimation({
    Key? key,
    required this.child,
    required this.cartKey,
    this.createAddToCartAnimation,
    this.createAnimationByQty,
    this.height = 30,
    this.width = 30,
    this.opacity = 0.85,
    this.jumpAnimation = const JumpAnimationOptions(),
    this.dragAnimation = const DragToCartAnimationOptions(),
  }) : super(key: key);

  @override
  _AddToCartAnimationState createState() => _AddToCartAnimationState();
}

class _AddToCartAnimationState extends State<AddToCartAnimation> {
  List<_PositionedAnimationModel> animationModels = [];

  @override
  void initState() {
    if (this.widget.createAddToCartAnimation != null) {
      this.widget.createAddToCartAnimation!(runAddToCartAnimation);
    }

    if (this.widget.createAnimationByQty != null) {
      this.widget.createAnimationByQty!(animationByQty);
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        widget.child,
        Positioned.fill(
          child: Stack(
            children: animationModels
                .map<Widget>((model) => model.showAnimation
                    ? AnimatedPositioned(
                        top: model.animationActive
                            ? model.imageDestPoint.dx
                            : model.imageSourcePoint.dx,
                        left: model.animationActive
                            ? model.imageDestPoint.dy
                            : model.imageSourcePoint.dy,
                        height: model.animationActive
                            ? model.imageDestSize.height
                            : model.imageSourceSize.height,
                        width: model.animationActive
                            ? model.imageDestSize.width
                            : model.imageSourceSize.width,
                        duration: model.duration,
                        curve: model.curve,
                        child: model.rotation
                            ? TweenAnimationBuilder(
                                tween: Tween<double>(begin: 0, end: pi * 2),
                                duration: model.duration,
                                child: model.container,
                                builder: (context, double value, widget) {
                                  return Transform.rotate(
                                    angle: value,
                                    child: Opacity(
                                      opacity: model.opacity,
                                      child: widget,
                                    ),
                                  );
                                },
                              )
                            : Opacity(
                                opacity: model.opacity,
                                child: model.container,
                              ),
                      )
                    : Container())
                .toList(),
          ),
        ),
      ],
    );
  }

  Future<void> animationByQty(GlobalKey widgetKey, int qty) async {
    for (var i = 0; i < qty; i++) {
      runAddToCartAnimation(widgetKey);
      await Future.delayed(const Duration(milliseconds: 200));
    }
  }

  Future<void> runAddToCartAnimation(GlobalKey widgetKey) async {
    _PositionedAnimationModel animationModel = _PositionedAnimationModel()
      ..rotation = false
      ..opacity = widget.opacity;

    animationModel.imageSourcePoint = Offset(
        widgetKey.globalPaintBounds!.top, widgetKey.globalPaintBounds!.left);

    // Improvement/Suggestion 1: Provinding option, in order to, use/or not initial "jumping" on image
    var startingHeight = widget.jumpAnimation.active
        ? widgetKey.currentContext!.size!.height
        : 0;
    animationModel.imageDestPoint = Offset(
        widgetKey.globalPaintBounds!.top - (startingHeight + widget.height),
        widgetKey.globalPaintBounds!.left);

    animationModel.imageSourceSize = Size(widgetKey.currentContext!.size!.width,
        widgetKey.currentContext!.size!.height);

    animationModel.imageDestSize = Size(
        widgetKey.currentContext!.size!.width + widget.width,
        widgetKey.currentContext!.size!.height + widget.height);

    animationModels.add(animationModel);
    // Improvement/Suggestion 2: Changing the animationModel.child from Image to gkImageContainer
    animationModel.container = Container(
      child: (widgetKey.currentWidget! as Container).child,
    );

    animationModel.showAnimation = true;

    setState(() {});

    await Future.delayed(Duration(milliseconds: 75));

    animationModel.curve = widget.jumpAnimation.curve;
    animationModel.duration =
        widget.jumpAnimation.duration; // This is for preview mode
    animationModel.animationActive = true; // That's start the animation.
    setState(() {});

    await Future.delayed(animationModel.duration);
    // Drag to cart animation
    animationModel.curve = widget.dragAnimation.curve;
    animationModel.rotation = widget.dragAnimation.rotation;
    animationModel.duration =
        widget.dragAnimation.duration; // this is for add to button mode

    animationModel.imageDestPoint = Offset(
        this.widget.cartKey.globalPaintBounds!.top,
        this.widget.cartKey.globalPaintBounds!.left);

    animationModel.imageDestSize = Size(
        this.widget.cartKey.currentContext!.size!.width,
        this.widget.cartKey.currentContext!.size!.height);

    setState(() {});

    await Future.delayed(animationModel.duration);
    animationModel.showAnimation = false;
    animationModel.animationActive = false;

    setState(() {});

    // Improvement/Suggestion 4.3: runCartAnimation is running independently, using gkCart.currentState(main.dart)
    // await this.widget.gkCart.currentState!.runCartAnimation();

    return;
  }
}

from add_to_cart_animation.

andre-ab avatar andre-ab commented on July 20, 2024

I temporarily solved it like this

Future<void> listClick(GlobalKey widgetKey, int quant) async {
  for (var i = 0; i < quant; i++) {
    runAddToCartAnimation(widgetKey);
    await Future.delayed(const Duration(milliseconds: 200));
  }
 cartTotalItems += quant;
  await cartKey.currentState!.runCartAnimation((cartTotalItems).toString());
}

from add_to_cart_animation.

omerbyrk avatar omerbyrk commented on July 20, 2024

It seems you already solved the issue. I am closing the issue. Thank you.

from add_to_cart_animation.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.