Flutter类似于电力输送的动画

news/2024/7/20 21:17:51 标签: flutter, visual studio code, ios, android
flutter_0">利用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),
            ],
          ),
        ),
      ),

简书地址


http://www.niftyadmin.cn/n/5252666.html

相关文章

基于SpringBoot的大学活动平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着互联网技术的不断…

如何在Go中构建For循环

引言 在计算机编程中,循环是一种代码结构,它循环地重复执行一段代码,通常直到满足某个条件。在计算机编程中使用循环可以使类似的任务自动化并重复多次。想象一下,如果你有一个需要处理的文件列表,或者你想计算一篇文章的行数。你可以在代码中使用循环来解决这类问题。 …

java8新特性之groupingBy的用法——全网独一无二的通俗易懂的讲解

文章目录 单级分组多级分组按子组收集数据 对于java8的新特性groupingBy方法&#xff0c;相信有很多人都在工作中用过&#xff0c;接下来就通俗易懂的讲解一下groupingBy吧 先来看看官网对于groupingBy方法的解释&#xff0c;groupingBy有个三个重载的方法&#xff0c;每一个重…

最新Redis7持久化(权威出版)

首先我们要知道什么是持久化&#xff1a;持久化是指将数据保存到磁盘上&#xff0c;以确保在Redis服务器重启时数据不会丢失。 Redis支持两种主要的持久化方式&#xff1a;RDB持久化和AOF持久化 下面让我依次给你介绍一下&#xff1a; RDB持久化 作用 这是将Redis数据保存…

快速幂 FastPower

「快速幂算法」的本质是 分治算法。例如,计算 x64,可以按照:x→x2→x4→x8→x16→x32→x64 的顺序,从 x 开始,每次直接把上一次的结果进行平方,计算 6 次就可以得到 x64 的值,而不需要对 x 乘 63 次 x。 50. Pow(x, n) 方法一:快速幂 + 递归 class Solution {public…

【MySQL】之联合索引与最左匹配原则

前言&#xff1a; 最左匹配原则在我们 MySQL 开发过程中和面试过程中经常遇到&#xff0c;为了加深印象和理解&#xff0c;我在这里把 MySQL 的最左匹配原则详细的讲解一下&#xff0c;包括它的原理以及是否导致索引失效的场景。 在讲解 MySQL 的最左匹配原则之前&#xff0c;…

leetcode 1004. 最大连续1的个数 III(优质解法)

代码&#xff1a; class Solution {public int longestOnes(int[] nums, int k) {int lengthnums.length;int zero0; //计数器&#xff0c;计数翻转 0 的个数int max0; //记录当前获得的最长子数组长度for(int left0,right0;right<length;right){if(nums[right]0){zero;wh…

Nmap脚本的价值和意义

Nmap脚本的价值和意义 Nmap脚本是一种基于Lua语言开发的脚本&#xff0c;可以扩展Nmap的功能&#xff0c;用于自动化扫描、漏洞检测、服务探测、设备管理等方面。在渗透测试领域中&#xff0c;Nmap脚本具有重要的价值和意义。本文将从渗透测试工程师的角度&#xff0c;详细介绍…