当前位置:网站首页>Flutter動畫入門: 內外逆向環Loading動畫
Flutter動畫入門: 內外逆向環Loading動畫
2022-06-22 12:26:00 【靜水流深zz】
系列文章
效果圖
標題有些拗口,一開始的標題好像觸發敏感詞了,所以只能這樣了


分析
很明顯這是由兩種顏色組成滴~
運動軌迹分別是裏面一個圈、外面一個圈。具體錶現為,外層兩個四分之一弧,內層兩個四分之一弧,且中心對稱。
內外相對運動,內圈速度要略慢一些,畢竟周長比較短(速度全憑個人喜好)~
按內外分為兩個widget,並對他們進行旋轉,就可以實現了。
弧度錶
來源網絡,這個下面會用到

繪制代碼
繪制中心對稱的兩個90度弧,使用CustomPaint即可實現。
以外部widget(黑色)為例,代碼如下:
CustomPaint(
painter: OuterPainter(),///傳入我們自己的 painter
)
class OuterPainter extends CustomPainter{
@override
void paint(Canvas canvas, Size size) {
///canvas 是我們作畫的畫布,Size則是父widget給我們的畫布大小
///也可以通過CustomPaint的size屬性指定,
///其次如果CustomPaint的child不為空,這個size的值會與child大小有關
///CustomPaint的size將被忽略
///初始化一個畫筆
Paint paint = Paint();
paint.color = Color.fromRGBO(51, 51, 51, 1);
paint.strokeWidth = 6;///畫筆粗細
paint.isAntiAlias = true;///抗鋸齒
paint.style = PaintingStyle.stroke;///默認是fill,我們不需要填充,選stroke
///首先我們需要一個矩形,畫布好根據這個矩形來確定圓的比特置(這個圓是抽象的)
Rect rect = Rect.fromCircle(center: Offset(size.width/2,size.height/2),radius: size.width/2);
/// drawArc 繪制一條弧線
/// 參數1 確定圓的矩形,
/// 參數2和3,分別是起始比特置和掃過的角度,它原名是叫startAngle 和 sweepAngle,
/// 0.0從中心點到右側0度 , 掃過pi/2 度 (90度),
/// 參數4(userCenter)false 只繪制一個弧線、如果是true,則會繪制一個扇形
/// 參數5 畫筆
canvas.drawArc(rect, 0.0, pi/2, false, paint);
///因為是中心對稱,所以我們將比特置移動180度
canvas.drawArc(rect, pi, pi/2, false, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false; ///如果你的painter和一個動畫綁定,理論上這裏應是true(或者根據自己需要的值進行判斷)錶示需要重繪
}
}
這樣我們就可以繪制出外面的widget了,同理可以繪制出裏面的,下面我們就開始讓他們轉了。
動畫代碼
我們可以直接使用 RotationTransition包裹我們的widget,並傳入對應的animation,通過animationController來控制。首先我們先定義animation,代碼如下:
AnimationController outerController,innerController;
Animation outerAnim,innerAnim;
@override
void initState() {
super.initState();
///使用動畫的頁面 要混入TickerProviderStateMixin,否則 vsync傳入參數this 會報錯,
/// 簡單的講,每次vsync信號回來的回調,會計算並更新動畫的值,在隨後刷新widget 便會看到改變
///(前提你的widget有值與動畫相關)
///參數2:動畫持續時間
outerController = AnimationController(vsync: this,duration: Duration(milliseconds:3000));
innerController = AnimationController(vsync: this,duration: Duration(milliseconds: 2000));
///補間動畫,begin和end的差可以理解為動畫的距離,可以看到外部要比內部的值,不管是從時間還是距離都要大一些
///,如果一致,內部的旋轉速度就會比外部的快了。
outerAnim = Tween(begin: 0.0,end: 2.0).animate(outerController);
innerAnim = Tween(begin: 1.0,end: 0.0).animate(innerController);
///分別為動畫的執行狀態,這個見名知意,不做贅述了。
innerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
innerController.reset();
innerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
innerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
outerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
outerController.reset();
outerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
outerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
}
這裏我們就完成了animation的定義,之後我們將outerAnim,innerAnim;分別傳給RotationTransition的turns參數即可。
完整代碼
class DemoPageState extends State<DemoPage> with TickerProviderStateMixin {
AnimationController outerController,innerController;
Animation outerAnim,innerAnim;
@override
void dispose() {
outerController?.dispose();
innerController?.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
outerController = AnimationController(vsync: this,duration: Duration(milliseconds:3000));
innerController = AnimationController(vsync: this,duration: Duration(milliseconds: 2000));
outerAnim = Tween(begin: 0.0,end: 2.0).animate(outerController);
innerAnim = Tween(begin: 1.0,end: 0.0).animate(innerController);
innerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
innerController.reset();
innerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
innerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
outerController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
outerController.reset();
outerController.forward();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
outerController.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
}
@override
Widget build(BuildContext context) {
if(!outerController.isAnimating)outerController.forward();
if(!innerController.isAnimating)innerController.forward();
return Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
alignment: Alignment.center,
children: <Widget>[
RotationTransition(
turns:outerAnim ,
child: Container(
width: 100,
height: 100,
child: CustomPaint(
painter: OuterPainter(),
),
),
),
RotationTransition(
turns: innerAnim,
child: Container(
width: 86,
height: 86,
child: CustomPaint(
painter: InnerPainter(),
),
),
),
],
),
],
),
);
}
}
DEMO
https://github.com/bladeofgod/flutter_loading
其他文章
边栏推荐
- Redis - 3、发布和订阅
- Error: unresolved variable $bus and "typeerror: cannot read property '$on' of undefined“
- Share 7 free super clear video resource stations! Both editing and collection are practical enough to cry!
- Traditional retail is accelerating the evolution and upgrading to new retail, and retail digitalization is imperative
- 第1章 自然语言处理和深度学习概述
- 推荐系统从入门到接着入门
- redisTemplate序列化
- 增长知识网
- 仿网易云音乐的滑动冲突处理效果
- Small demo of QT page layout class
猜你喜欢
随机推荐
Numpy库常用功能 合并
Word技巧汇总
Redis - 11. Cluster
New progress in the construction of meituan's Flink based real-time data warehouse platform
linux设置 让oracle10g自启动
[lihongyi] notes on deep learning of machine learning -- Introduction to training model clearance
查看gstreamer插件
JMeter generates test reports
Small demo of QT page layout class
Struggle, programmer -- Chapter 41 all kinds of things today are like water without trace; On the eve of the Ming Dynasty, you are a stranger
How to count the growth of daily business data from the database level?
ppt数据采集方法与分析技能
Could not determine which parameter to assign generated keys to
推荐系统从入门到接着入门
Some concepts that the initial transformer needs to understand
getenv、setenv函数(获取和设置系统环境变量) 与 环境变量
Es aggregation details
DevSecOps: CI/CD 流水线安全的最佳实践
Heavyweight live | bizdevops: the way to break the technology situation under the tide of digital transformation
机器学习与深度学习 --- 激活函数(未完待续)





![[cloud native | kubernetes] Introduction to kubernetes (I)](/img/e0/c75e72fc3636b3de8f5caded19a883.png)



