Old Meng guide: today to share how to achieve the effect of digging gold praise, this is not only a technical article, but also a solution to the problem idea article, when meeting a demand, how to split the demand, and then step by step to achieve, this process is more valuable than pure technology (this article).

Here’s a look at the nuggets’ likes:

A little digress, thanks to the second brother (silent King two), gave me a lot of advice and help, the public search silent King two can be concerned.

When encountering the combined animation effect, first split this animation, taking the gold digging effect as an example, it is divided into three animation effects:

  1. The little hand icon changes color and zooms in.
  2. The ring changes from thick to thin, and its transparency gradually becomes 0.
  3. The outermost dot becomes zero in transparency.

Once you’ve broken it down, step by step you can achieve it.

Small hand zoom effect

The small hand zoom effect requires 2 ICONS, both selected and unselected. I selected 2 similar ICONS from Ali’s icon library (I didn’t find any identical ICONS). The ICONS for the two states are defined as follows:

///
/// Thumb up icon
///
const Icon _unLikeIcon = Icon(
  IconData(0xe60a, fontFamily: 'appIconFonts'));///
/// Thumb up icon
///
const Icon _likeIcon = Icon(
  IconData(0xe60c, fontFamily: 'appIconFonts'),
  color: Color(0xFF1afa29));Copy the code

Check out this article on how to use the ICONS in Ali’s icon library.

Since the animation effect of the small hand icon is enlarged -> restore, use the combination animation to achieve its effect, the code is as follows:

@override
initState() {
  _animationController =
      AnimationController(duration: Duration(milliseconds: 300), vsync: this);


  _iconAnimation = Tween(begin: 1.0, end: 1.3).animate(_animationController);

  _iconAnimation = TweenSequence([
    TweenSequenceItem(
        tween: Tween(begin: 1.0, end: 1.3)
            .chain(CurveTween(curve: Curves.easeIn)),
        weight: 50),
    TweenSequenceItem(tween: Tween(begin: 1.3, end: 1.0), weight: 50),
  ]).animate(_animationController);
}

@override
  Widget build(BuildContext context) {
    return _buildLikeIcon();
  }

_buildLikeIcon() {
    return ScaleTransition(
      scale: _iconAnimation,
      child: widget.like
          ? IconButton(
              padding: EdgeInsets.all(0),
              icon: _likeIcon,
              onPressed: () {
                _clickIcon();
              },
            )
          : IconButton(
              padding: EdgeInsets.all(0), icon: _unLikeIcon, onPressed: () { _clickIcon(); },),); }Copy the code

Add button click effect:

_clickIcon() {
  if (_iconAnimation.status == AnimationStatus.forward ||
      _iconAnimation.status == AnimationStatus.reverse) {
    return; } setState(() { widget.like = ! widget.like; });if (_iconAnimation.status == AnimationStatus.dismissed) {
    _animationController.forward();
  } else if(_iconAnimation.status == AnimationStatus.completed) { _animationController.reverse(); }}Copy the code

Circle the animation

The animation effect of the ring is that the line width gradually decreases to 0 and the transparency gradually decreases to 0. It is relatively simple, using AnimatedBuilder:

_buildCircle() {
  return! widget.like ? Container() : AnimatedBuilder( animation: _circleAnimation, builder: (BuildContext context, Widget child) {return Container(
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  border: Border.all(
                      color: Color(0xFF5FA0EC)
                          .withOpacity(_circleAnimation.value),
                      width: _circleAnimation.value * 8))); }); }Copy the code

Define _circleAnimation * * * * :

_circleAnimation =
    Tween(begin: 1.0, end: 0.0).animate(_animationController);
Copy the code

The outermost circle is a little bit smaller

The little dots in the outermost circle have the simplest animation effect, with the transparency gradually turning to 0. However, the layout is relatively complex, forming a circle around the hands. Use Flow to achieve this layout.

Construct a single dot

_buildCirclePoint(double radius, Color color) {
  return! widget.like ? Container() : AnimatedBuilder( animation: _circleAnimation, builder: (BuildContext context, Widget child) {returnContainer( width: radius, height: radius, decoration: BoxDecoration( shape: BoxShape.circle, color: color.withOpacity(_circleAnimation.value)), ); }); }Copy the code

Build multiple points around small hands:

_buildCirclePoints() {
  return Flow(
    delegate: CirclePointFlowDelegate(),
    children: <Widget>[
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),
      _buildCirclePoint(2, Color(0xFF97B1CE)),
      _buildCirclePoint(5, Color(0xFF4AC6B7)),,); }Copy the code

The CirclePointFlowDelegate is defined as follows:

class CirclePointFlowDelegate extends FlowDelegate {
  CirclePointFlowDelegate();

  @override
  void paintChildren(FlowPaintingContext context) {
    var radius = min(context.size.width, context.size.height) / 2.0;
    / / center
    double rx = radius;
    double ry = radius;
    for (int i = 0; i < context.childCount; i++) {
      if (i % 2= =0) {
        double x =
            rx + (radius - 5) * cos(i * 2 * pi / (context.childCount - 1));
        double y =
            ry + (radius - 5) * sin(i * 2 * pi / (context.childCount - 1));
        context.paintChild(i, transform: Matrix4.translationValues(x, y, 0));
      } else {
        double x = rx +
            (radius - 5) *
                cos((i - 1) * 2 * pi / (context.childCount - 1) +
                    2 * pi / ((context.childCount - 1) * 3));
        double y = ry +
            (radius - 5) *
                sin((i - 1) * 2 * pi / (context.childCount - 1) +
                    2 * pi / ((context.childCount - 1) * 3));
        context.paintChild(i, transform: Matrix4.translationValues(x, y, 0)); }}}@override
  bool shouldRepaint(FlowDelegate oldDelegate) => true;
}
Copy the code

communication

Old Meng Flutter blog address (nearly 200 controls usage) : laomengit.com