Пульсация анимации дрожания

Я хочу создать анимацию ряби с помощью флаттера. Я уже знаю эффект пульсации, но это не то, что я хочу, я хочу что-то, что есть здесь, в ссылка


person primo    schedule 10.04.2019    source источник


Ответы (3)


Выход

введите описание изображения здесь

  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      lowerBound: 0.5,
      duration: Duration(seconds: 3),
    )..repeat();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Title")),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    return AnimatedBuilder(
      animation: CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn),
      builder: (context, child) {
        return Stack(
          alignment: Alignment.center,
          children: <Widget>[
            _buildContainer(150 * _controller.value),
            _buildContainer(200 * _controller.value),
            _buildContainer(250 * _controller.value),
            _buildContainer(300 * _controller.value),
            _buildContainer(350 * _controller.value),
            Align(child: Icon(Icons.phone_android, size: 44,)),
          ],
        );
      },
    );
  }

  Widget _buildContainer(double radius) {
    return Container(
      width: radius,
      height: radius,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.blue.withOpacity(1 - _controller.value),
      ),
    );
  }
person CopsOnRoad    schedule 10.04.2019
comment
Мне нужна еще одна помощь. Я хочу выровнять это по центру внизу всего макета. Я пытаюсь, но не понимаю - person primo; 10.04.2019
comment
Оберните AnimatedBuilder в Align и замените alignment на Alignment.bottomCenter - person CopsOnRoad; 10.04.2019
comment
Я сделал это Виджет колонки - person primo; 10.04.2019
comment
Это действительно отличный ответ. Большое спасибо! - person Konstantin; 22.06.2019
comment
with TickerProviderStateMixin Добавьте этот миксин в свой класс состояния, если вы получили ошибку на vsync - person Devinder Jhinjer; 20.05.2020
comment
Как я могу добавить эту анимацию в текущее местоположение карты Google (флаттер)? - person Rohit Luthra; 20.05.2020
comment
@RohitLuthra В прошлый раз, когда я использовал карты Google, он не поддерживал отображение обычного виджета flutter в качестве маркера, и на Github возникла проблема, поэтому не уверен, сможете ли вы отображать виджеты сегодня. - person CopsOnRoad; 21.05.2020
comment
Действительно помогло @CopsOnRoad - person sainu; 05.05.2021

Вот еще одна версия с использованием CustomPaint

import 'dart:math' as math show sin, pi, sqrt;

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';

class Ripples extends StatefulWidget {
  const Ripples({
    Key key,
    this.size = 80.0,
    this.color = Colors.pink,
    this.onPressed,
    @required this.child,
  }) : super(key: key);

  final double size;
  final Color color;
  final Widget child;
  final VoidCallback onPressed;

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

class _CirclePainter extends CustomPainter {
  _CirclePainter(
    this._animation, {
    @required this.color,
  }) : super(repaint: _animation);

  final Color color;
  final Animation<double> _animation;

  void circle(Canvas canvas, Rect rect, double value) {
    final double opacity = (1.0 - (value / 4.0)).clamp(0.0, 1.0);
    final Color _color = color.withOpacity(opacity);

    final double size = rect.width / 2;
    final double area = size * size;
    final double radius = math.sqrt(area * value / 4);

    final Paint paint = Paint()..color = _color;
    canvas.drawCircle(rect.center, radius, paint);
  }

  @override
  void paint(Canvas canvas, Size size) {
    final Rect rect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);

    for (int wave = 3; wave >= 0; wave--) {
      circle(canvas, rect, wave + _animation.value);
    }
  }

  @override
  bool shouldRepaint(_CirclePainter oldDelegate) => true;
}

class _RipplesState extends State<Ripples> with TickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 2000),
      vsync: this,
    )..repeat();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Widget _button() {
    return Center(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(widget.size),
        child: DecoratedBox(
          decoration: BoxDecoration(
            gradient: RadialGradient(
              colors: <Color>[
                widget.color,
                Color.lerp(widget.color, Colors.black, .05)
              ],
            ),
          ),
          child: ScaleTransition(
            scale: Tween(begin: 0.95, end: 1.0).animate(
              CurvedAnimation(
                parent: _controller,
                curve: const _PulsateCurve(),
              ),
            ),
            child: widget.child,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _CirclePainter(
        _controller,
        color: widget.color,
      ),
      child: SizedBox(
        width: widget.size * 2.125,
        height: widget.size * 2.125,
        child: _button(),
      ),
    );
  }
}

class _PulsateCurve extends Curve {
  const _PulsateCurve();

  @override
  double transform(double t) {
    if (t == 0 || t == 1) {
      return 0.01;
    }
    return math.sin(t * math.pi);
  }
}
person jogboms    schedule 15.04.2019
comment
Господи ... столько шаблонов для простой вещи! - person U Avalos; 21.05.2019
comment
Это не так просто, как можно было бы ожидать. Это всего лишь альтернативная реализация с использованием рисовальщиков. - person jogboms; 22.05.2019
comment
Вы не поверите, но это более эффективное решение, чем принятое решение. CustomPainter подробный, но эффективный AF, и даже этот фрагмент лучше, чем java-решения, в которых вы должны установить библиотеку только для этого - person ValdaXD; 19.09.2020

Этого также можно добиться, используя этот исходный код flutter_ripple_animation_demo

просто добавьте этот файл в свой проект и используйте их, как показано ниже

Пример здесь

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'package:rippledemo/circle_painter.dart';
import 'package:rippledemo/curve_wave.dart';


class RipplesAnimation extends StatefulWidget {
  const RipplesAnimation({Key key, this.size = 80.0, this.color = Colors.red,
    this.onPressed, @required this.child,}) : super(key: key);
  final double size;
  final Color color;
  final Widget child;
  final VoidCallback onPressed;
  @override
  _RipplesAnimationState createState() => _RipplesAnimationState();
}

class _RipplesAnimationState extends State<RipplesAnimation> with TickerProviderStateMixin {
  AnimationController _controller;
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 2000),
      vsync: this,
    )..repeat();
  }
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  Widget _button() {
    return Center(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(widget.size),
        child: DecoratedBox(
          decoration: BoxDecoration(
            gradient: RadialGradient(
              colors: <Color>[
                widget.color,
                Color.lerp(widget.color, Colors.black, .05)
              ],
            ),
          ),
          child: ScaleTransition(
              scale: Tween(begin: 0.95, end: 1.0).animate(
                CurvedAnimation(
                  parent: _controller,
                  curve: const CurveWave(),
                ),
              ),
              child: Icon(Icons.speaker_phone, size: 44,)
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Ripple Demo"),
      ),
      body: Center(
        child: CustomPaint(
          painter: CirclePainter(
            _controller,
            color: widget.color,
          ),
          child: SizedBox(
            width: widget.size * 4.125,
            height: widget.size * 4.125,
            child: _button(),
          ),
        ),
      ),
    );
  }
}

введите описание изображения здесь

person Paresh Mangukiya    schedule 12.05.2021