Flutter类似于电力输送的动画

利用flutter写了个类似于充电的动画,比如光伏板给电池充电,模仿电力输送的过程,效果如下图所示

gif.gif

下面直接贴出代码,属性都标注了注释,使用的时候在外面加个盒子固定宽高,然后给出每个点的坐标,内部会根据坐标的点数来判断有几根线,然后画出线的路径,进行动画模拟,可以根据项目需求来自定义点的颜色,每条路径上点的个数以及点的大小等等,
import 'package:flutter/material.dart';

class ElectricAnimated extends StatelessWidget {
  final int duration; //动画时长
  final List<Offset> path; //路径的点坐标
  const ElectricAnimated({
    super.key,
    this.duration = 5,
    required this.path,
  });

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: List.generate(
        path.length - 1,
        (index) {
          return AnimatedDots(
            path: [
              path[index],
              path[index + 1],
            ],
            dotCount: 3,
            duration: Duration(
              seconds: duration,
            ),
          );
        },
      ),
    );
  }
}

class AnimatedDots extends StatefulWidget {
  final List<Offset> path; //路径的点坐标
  final int dotCount; //每条路径上的点的个数
  final double dotSize; //点的大小
  final Duration duration;
  final Color dotColor; //点的颜色

  const AnimatedDots({
    Key? key,
    required this.path,
    this.dotCount = 5,
    this.dotSize = 2,
    this.duration = const Duration(seconds: 2),
    this.dotColor = Colors.white,
  }) : super(key: key);

  @override
  State<AnimatedDots> createState() => _AnimatedDotsState();
}

class _AnimatedDotsState extends State<AnimatedDots>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;
  int _currentIndex = 0;

  @override
  void initState() {
    super.initState();

    _animationController = AnimationController(
      vsync: this,
      duration: widget.duration,
    );

    _animation = Tween<double>(
      begin: 0,
      end: 1,
    ).animate(_animationController);

    _animationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _currentIndex++;
        if (_currentIndex >= widget.path.length - 1) {
          _currentIndex = 0;
        }

        _animationController.reset();
        _animationController.forward();
      }
    });

    _animationController.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        final value = _animation.value;
        final current = widget.path[_currentIndex];
        final next = widget.path[(_currentIndex + 1) % widget.path.length];

        final dots = List.generate(widget.dotCount, (index) {
          final dotValue = (value + index / widget.dotCount) % 1;
          final x = current.dx + (next.dx - current.dx) * dotValue;
          final y = current.dy + (next.dy - current.dy) * dotValue;

          return Positioned(
            left: x - widget.dotSize / 2,
            top: y - widget.dotSize / 2,
            child: Container(
              width: widget.dotSize,
              height: widget.dotSize,
              decoration: BoxDecoration(
                color: widget.dotColor,
                shape: BoxShape.circle,
              ),
            ),
          );
        });

        return Stack(
          children: dots,
        );
      },
    );
  }
}

使用

body: Center(
        child: Container(
          color: Colors.black,
          width: 150,
          height: 150,
          child: const ElectricAnimated(
            duration: 3,
            path: [
              Offset(30, 0),
              Offset(30, 67),
              Offset(90, 67),
              Offset(90, 137),
            ],
          ),
        ),
      ),

简书地址

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Flutter中的缩放动画`ScaleTransition`来实现控件的变大变小动画效果。具体实现步骤如下所示: 1.在需要实现动画的控件外包裹一个`ScaleTransition`组件。 2.设置`ScaleTransition`组件的`scale`属性值,该属性值表示控件的缩放比例。 3.在需要触发动画的时候调用`ScaleTransition`组件的`controller`对象的`forward()`方法触发动画。 下面是一个简单的示例代码,实现一个圆形控件的变大变小动画: ```dart class ScaleAnimationWidget extends StatefulWidget { @override State<StatefulWidget> createState() => _ScaleAnimationWidgetState(); } class _ScaleAnimationWidgetState extends State<ScaleAnimationWidget> with SingleTickerProviderStateMixin { AnimationController _controller; // 动画控制器 Animation<double> _animation; // 动画对象 @override void initState() { super.initState(); // 创建动画控制器 _controller = AnimationController( duration: const Duration(milliseconds: 500), vsync: this); // 创建动画对象,从1倍放大到2倍 _animation = Tween(begin: 1.0, end: 2.0).animate(_controller) ..addListener(() { setState(() {}); }); } @override Widget build(BuildContext context) { return Center( child: GestureDetector( onTap: () { if (_controller.status == AnimationStatus.completed) { _controller.reverse(); // 反向播放动画 } else { _controller.forward(); // 正向播放动画 } }, child: ScaleTransition( scale: _animation, // 设置缩放比例 child: Container( width: 100, height: 100, decoration: BoxDecoration( color: Colors.blue, shape: BoxShape.circle, ), ), ), ), ); } } ``` 在上述代码中,我们创建了一个圆形控件,然后将其包裹在一个`ScaleTransition`组件中。当用户点击该圆形控件时,会根据动画控制器的状态正向或反向播放缩放动画
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值