Flutter 3D旋转
废话就不多说了,主要是用到了Flutter Tranform来做图形变换,然后利用PageView来做分页的控制.一个四个页面,算出四个页面之间旋转的百分比大概为0.25.
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
PageController _pageController = PageController(initialPage: 1);
double animationRotationValue = 0;
double screenWidth = 0;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_pageController.addListener(() {
if(_pageController.page == 0) { // 循环滚动
_pageController.jumpToPage(4);
}
if(_pageController.page == 5) { // 循环滚动
_pageController.jumpToPage(1);
}
double offset = _pageController.offset / screenWidth * 0.25;
setState(() {
animationRotationValue = offset * math.pi * 2;
});
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
bool isOnLeft(double rotation) => math.cos(rotation) > 0;
@override
Widget build(BuildContext context) {
final numberOfTexts = 4;
final size = MediaQuery.of(context).size;
screenWidth = size.width;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Positioned.fill(
child: Container(
width: double.infinity,
height: double.infinity,
child: Stack(
alignment: Alignment.center,
children: List.generate(
numberOfTexts,
(index) {
return AnimatedBuilder(
animation: _animationController,
child: Container(
height: 300,
width: 200,
alignment: Alignment.center,
child: Transform( /// 翻转页面
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..translate(20.0)
..rotateY(math.pi),
child: Text("$index", style: TextStyle(fontSize: 30, color: Colors.white, fontWeight: FontWeight.bold),),
),
decoration: BoxDecoration(
color: Colors.white,
gradient: LinearGradient(
colors: [
Colors.transparent,
Colors.blue.withOpacity(0.9),
Colors.transparent
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
stops: [0.0, 0, 1],
),
),
),
builder: (context, child) {
double rotation = 2 * math.pi * index / numberOfTexts +
math.pi / 2 +
animationRotationValue;
// if (isOnLeft(rotation)) {
// rotation = -rotation +
// 2 * animationRotationValue -
// math.pi * 2 / numberOfTexts;
// }
return Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(rotation)
..translate(.0, 0.0, 150.0)
,
child: child
);
},
);
},
),
),
),
),
Positioned.fill(
child: PageView.builder(
itemCount: numberOfTexts + 2,
controller: _pageController,
itemBuilder: (context, index) {
return Container();
}
)
)
],
),
),
);
}
}