Flutter 颤振中的三维旋转木马动画
如何使用颤振创建类似的效果?我为您做了一个调整,调整Matrix4参数。 (模糊/景深在浏览器上无法正常工作)Flutter 颤振中的三维旋转木马动画,flutter,flutter-layout,flutter-animation,Flutter,Flutter Layout,Flutter Animation,如何使用颤振创建类似的效果?我为您做了一个调整,调整Matrix4参数。 (模糊/景深在浏览器上无法正常工作) import'dart:math'; 导入“dart:ui”; 进口“包装:颤振/材料.省道”; void main()=>runApp(MyApp()); 类MyApp扩展了无状态小部件{ @凌驾 小部件构建(构建上下文){ 返回材料PP( debugShowCheckedModeBanner:false, 黑暗主题: 主题数据(平台:TargetPlatform.iOS,亮度:亮度
import'dart:math';
导入“dart:ui”;
进口“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
debugShowCheckedModeBanner:false,
黑暗主题:
主题数据(平台:TargetPlatform.iOS,亮度:亮度.暗),
主:旋转场景(),
);
}
}
类RotationScene扩展StatefulWidget{
@凌驾
_RotationSceneState createState()=>\u RotationSceneState();
}
类_RotationSceneState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:正文(
“卡鲁塞尔”,
样式:TextStyle(字体大小:13),
),
标题:错误,
标高:12,
背景颜色:颜色。透明,
),
主体:容器(
装饰:盒子装饰(
梯度:线性梯度(
开始:Alignment.topLeft,
结束:对齐。右下角,
颜色:[颜色(0xff74ABE4),颜色(0xffA892ED)],
停止:[0,1],
)),
子:中心(子:MyScener()),
),
);
}
}
类卡片数据{
颜色;
双x,y,z,角;
最终int idx;
双α=0;
颜色变浅{
var val=HSVColor.fromColor(颜色);
返回val.withSaturation(.5).withValue.toColor();
}
CardData(this.idx){
color=Colors.primaries[idx%Colors.primaries.length];
x=0;
y=0;
z=0;
}
}
类MyScener扩展StatefulWidget{
@凌驾
_MyScenerState createState()=>\u MyScenerState();
}
类_MyScenerState扩展状态
使用SingleTickerProviderStateMixin{
AnimationController _AnimationController;
列表cardData=[];
int numItems=9;
双无线电=200.0;
双无线电步进;
int centerIdx=1;
@凌驾
void initState(){
cardData=List.generate(numItems,(index)=>cardData(index)).toList();
radioStep=(pi*2)/numItems;
_动画控制器=
AnimationController(vsync:this,duration:duration(秒数:1));
_addListener(()=>setState((){}));
_animationController.addStatusListener((状态)异步{
如果(状态==AnimationStatus.completed){
_animationController.value=0;
_animationController.animateTo(1);
++centerIdx;
}
});
_animationController.forward();
super.initState();
}
@凌驾
小部件构建(构建上下文){
变量比率=_animationController.value;
双值=中心IDX+比率;
//处理位置。
对于(变量i=0;ia.z.compareTo(b.z));
var list=cardData.map((vo){
var c=添加卡(vo);
var mt2=Matrix4.identity();
mt2.setEntry(3,2,0.001);
mt2.翻译(vo.x,vo.y,-vo.z);
mt2.旋转(vo.角度+pi);
c=变换(
对齐:对齐.center,
原点:偏移(0.0,-0.0),
转换:mt2,
孩子:c,
);
//景深…在网络上不起作用。
//变量模糊=.4+((1-vo.z/radio)/2)*2;
//c=反降滤波器(
//过滤器:ImageFilter.blur(sigmaX:blur,sigmaY:blur),
//孩子:c,
// );
返回c;
}).toList();
返回容器(
对齐:对齐.center,
子:堆栈(
对齐:对齐.center,
儿童:名单,
),
);
}
小部件添加卡(CardData vo){
变量α=((1-vo.z/radio)/2)*.6;
小部件c;
c=集装箱(
保证金:所有(12),
宽度:120,
身高:80,
对齐:对齐.center,
前场装饰:盒子装饰(
边界半径:边界半径。圆形(12),
颜色:颜色。黑色。不透明度(alpha),
),
装饰:盒子装饰(
梯度:线性梯度(
开始:Alignment.topLeft,
结束:对齐。右下角,
停止:[0.1,.9],
颜色:[vo.lightColor,vo.color],
),
边界半径:边界半径。圆形(12),
boxShadow:[
箱形阴影(
颜色:颜色。黑色。不透明度(.2+alpha*.2),
扩展半径:1,
半径:12,
偏移量:偏移量(0,2))
],
),
子项:Text('ITEM${vo.idx}'),
);
返回c;
}
}
我为您做了一个调整,调整Matrix4参数。
(模糊/景深在浏览器上无法正常工作)
import'dart:math';
导入“dart:ui”;
进口“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
debugShowCheckedModeBanner:false,
黑暗主题:
主题数据(平台:TargetPlatform.iOS,亮度:亮度.暗),
主:旋转场景(),
);
}
}
类RotationScene扩展StatefulWidget{
@凌驾
_RotationSceneState createState()=>\u RotationSceneState();
}
类_RotationSceneState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:正文(
“卡鲁塞尔”,
样式:TextStyle(字体大小:13),
),
标题:错误,
标高:12,
背景颜色:颜色。透明,
),
主体:容器(
装饰:盒子装饰(
梯度:线性梯度(
开始:Alignment.topLeft,
结束:对齐。右下角,
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
darkTheme:
ThemeData(platform: TargetPlatform.iOS, brightness: Brightness.dark),
home: RotationScene(),
);
}
}
class RotationScene extends StatefulWidget {
@override
_RotationSceneState createState() => _RotationSceneState();
}
class _RotationSceneState extends State<RotationScene> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'carrousel',
style: TextStyle(fontSize: 13),
),
centerTitle: false,
elevation: 12,
backgroundColor: Colors.transparent,
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xff74ABE4), Color(0xffA892ED)],
stops: [0, 1],
)),
child: Center(child: MyScener()),
),
);
}
}
class CardData {
Color color;
double x, y, z, angle;
final int idx;
double alpha = 0;
Color get lightColor {
var val = HSVColor.fromColor(color);
return val.withSaturation(.5).withValue(.8).toColor();
}
CardData(this.idx) {
color = Colors.primaries[idx % Colors.primaries.length];
x = 0;
y = 0;
z = 0;
}
}
class MyScener extends StatefulWidget {
@override
_MyScenerState createState() => _MyScenerState();
}
class _MyScenerState extends State<MyScener>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
List<CardData> cardData = [];
int numItems = 9;
double radio = 200.0;
double radioStep;
int centerIdx = 1;
@override
void initState() {
cardData = List.generate(numItems, (index) => CardData(index)).toList();
radioStep = (pi * 2) / numItems;
_animationController =
AnimationController(vsync: this, duration: Duration(seconds: 1));
_animationController.addListener(() => setState(() {}));
_animationController.addStatusListener((status) async {
if (status == AnimationStatus.completed) {
_animationController.value = 0;
_animationController.animateTo(1);
++centerIdx;
}
});
_animationController.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
var ratio = _animationController.value;
double animValue = centerIdx + ratio;
// process positions.
for (var i = 0; i < cardData.length; ++i) {
var c = cardData[i];
double ang = c.idx * radioStep + animValue;
c.angle = ang + pi / 2;
c.x = cos(ang) * radio;
// c.y = sin(ang) * 10;
c.z = sin(ang) * radio;
}
// sort in Z axis.
cardData.sort((a, b) => a.z.compareTo(b.z));
var list = cardData.map((vo) {
var c = addCard(vo);
var mt2 = Matrix4.identity();
mt2.setEntry(3, 2, 0.001);
mt2.translate(vo.x, vo.y, -vo.z);
mt2.rotateY(vo.angle + pi);
c = Transform(
alignment: Alignment.center,
origin: Offset(0.0, -0.0),
transform: mt2,
child: c,
);
// depth of field... doesnt work on web.
// var blur = .4 + ((1 - vo.z / radio) / 2) * 2;
// c = BackdropFilter(
// filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
// child: c,
// );
return c;
}).toList();
return Container(
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
children: list,
),
);
}
Widget addCard(CardData vo) {
var alpha = ((1 - vo.z / radio) / 2) * .6;
Widget c;
c = Container(
margin: EdgeInsets.all(12),
width: 120,
height: 80,
alignment: Alignment.center,
foregroundDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.black.withOpacity(alpha),
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0.1, .9],
colors: [vo.lightColor, vo.color],
),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(.2 + alpha * .2),
spreadRadius: 1,
blurRadius: 12,
offset: Offset(0, 2))
],
),
child: Text('ITEM ${vo.idx}'),
);
return c;
}
}