马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
媒介:
之前一直看到 有手机充电的时候 有气泡从Type-C 的位置冒泡上来 逐步上移, 然后和上面的圆圈 会和,感觉照旧挺好看的。今天试了下用 Flutter 实现了一版本。大致结果如下,而且气泡 和 气泡直接还可以粘黏
实现原理:
大致的布局就是如许的: Stack 包裹住全部的元素,需要位置移动的是 AnimatedBuilder,这里是把他们独立出来,方便随机的时候打散处置惩罚。
代码实现:
- PageBubble.dart 整个页面 气泡的粘连结果 有点吃性能
- import 'dart:math';
- import 'dart:ui';
- import 'package:flutter/material.dart';
- import 'package:untitled1a/pages/example1/bubble_dot.dart';
- class PageBubble extends StatefulWidget {
- const PageBubble({Key? key}) : super(key: key);
- @override
- State<PageBubble> createState() => _PageBubbleState();
- }
- class _PageBubbleState extends State<PageBubble>
- with SingleTickerProviderStateMixin {
- late AnimationController _animationController;
- final Random random = Random();
- @override
- void initState() {
- _animationController = AnimationController(
- vsync: this,
- duration: const Duration(milliseconds: 2500),
- );
- _animationController.repeat();
- super.initState();
- }
- @override
- void dispose() {
- _animationController.dispose();
- // TODO: implement dispose
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- backgroundColor: Theme.of(context).colorScheme.inversePrimary,
- title: Text('充电气泡'),
- ),
- body: Align(
- alignment: Alignment(0.0, 1),
- child: Container(
- height: MediaQuery.of(context).size.height / 3 * 2,
- width: 250,
- // color: Colors.blue,
- child: Stack(
- alignment: Alignment.topCenter,
- children: [
- ...buildAnimatedPositioned(),
- Padding(
- padding: const EdgeInsets.only(
- top: 40,
- left: 0,
- ),
- child: RotationTransition(
- alignment: Alignment.center,
- turns: _animationController,
- child: Container(
- width: 200,
- height: 200,
- decoration: const BoxDecoration(
- color: Colors.deepPurple,
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(70),
- topLeft: Radius.circular(90),
- bottomRight: Radius.circular(60),
- bottomLeft: Radius.circular(80),
- ),
- ),
- ),
- ),
- ),
- //这个效果很有意思 就是有费性能 不需要可以移除掉
- BackdropFilter(
- filter: ImageFilter.dilate(radiusX: 3.0, radiusY: 3.0),
- child: Container(),
- ),
- Positioned(
- left: 35,
- top: 45,
- child: Container(
- width: 180,
- height: 180,
- decoration: BoxDecoration(
- color: Colors.black,
- borderRadius: BorderRadius.circular(90),
- ),
- child: const Center(
- child: Text(
- '89%',
- style: TextStyle(
- fontSize: 40,
- color: Colors.white,
- ),
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- );
- }
- int getRandomNumber(int min, int max) {
- var random = Random();
- return min + random.nextInt(max - min + 1);
- }
- List<Widget> buildAnimatedPositioned() {
- List<Widget> _list = [];
- List.generate(
- 9,
- (index) => {
- _list.add(BubbleDot(time: getRandomNumber(2000, 3500))),
- });
- return _list;
- }
- }
复制代码
- BubbleDot.dart 气泡结果 之所以把气泡单独出来是为了后面的随机打散操纵
- import 'dart:math';
- import 'package:flutter/material.dart';
- class BubbleDot extends StatefulWidget {
- final int time;
- const BubbleDot({super.key, required this.time});
- @override
- State<BubbleDot> createState() => _BubbleDotState();
- }
- class _BubbleDotState extends State<BubbleDot>
- with SingleTickerProviderStateMixin {
- late AnimationController _animationController;
- late Animation<double> _animation;
- final Random random = Random();
- late double _leftPos = 0;
- late double _dotWidth = 0;
- @override
- void initState() {
- _animationController = AnimationController(
- vsync: this,
- duration: Duration(milliseconds: widget.time),
- );
- _animation = _animationController.drive(
- Tween<double>(begin: getRandomNumber(660, 800).toDouble(), end: 100));
- //_leftPos = random.nextDouble() * 200;
- _leftPos = getRandomNumber(35, 180).toDouble();
- _dotWidth = getRandomNumber(30, 66).toDouble();
- _animationController.addStatusListener(
- (AnimationStatus status) => {print('status $status')});
- _animationController.repeat();
- // TODO: implement initState
- super.initState();
- }
- @override
- void dispose() {
- // TODO: implement dispose
- _animationController.dispose();
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return AnimatedBuilder(
- animation: _animation,
- builder: (BuildContext context, Widget? child) {
- return Positioned(
- top: _animation.value,
- //top: 240,
- left: _leftPos,
- child: ClipOval(
- child: Container(
- width: _dotWidth,
- height: _dotWidth,
- decoration: BoxDecoration(
- color: Colors.deepPurple,
- boxShadow: [
- BoxShadow(
- color: Colors.deepPurple.withOpacity(0.5),
- spreadRadius: 6,
- blurRadius: 8,
- offset: Offset(4, 4), // changes position of shadow
- ),
- ],
- ),
- ),
- ),
- );
- },
- );
- }
- int getRandomNumber(int min, int max) {
- return min + random.nextInt(max - min + 1);
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |