最近通過一篇部落格學習了Flutter中的3D透視效果。
效果是跟隨手指的觸控,介面做3D轉動。
// v2: add Gesture detector
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Perspective',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key); // changed
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Offset _offset = Offset.zero; // changed
@override
Widget build(BuildContext context) {
return Transform(
// Transform widget
transform: Matrix4.identity() //生成一個單位矩陣
..setEntry(3, 2, 0.001) // 透視
..rotateX(0.01 * _offset.dy) // changed
..rotateY(-0.01 * _offset.dx), // changed
alignment: FractionalOffset.center,
child: GestureDetector(
// new
onPanUpdate: (details) =>
setState(() => _offset += details.delta), //與螢幕接觸並移動的指標再次移動
onDoubleTap: () => setState(() => _offset = Offset.zero),
child: _defaultApp(context),
));
}
_defaultApp(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'3D效果',
),
],
),
),
);
}
}
複製程式碼
主要用到了Transform
。Transform
是用來做矩陣變換的。
首先通過Matrix4.identity()
來生成一個單位矩陣。然後通過..setEntry(3, 2, 0.001)
來將矩陣的第3行第2列設定為0.001。作用是類似設定物體到攝像機的距離,越遠物體看起來越小,越近看起來物體越大。
..rotateX
和..rotateY
是分別修改XY軸的數值,這裡乘0.01是做了一個數值壓縮。(因為是以Z軸為軸做旋轉,所以改變的是X和Y軸的值,Z軸是垂直於螢幕方向的軸)。
最後通過GestureDetector
部件獲取手指移動的距離,並新增雙擊復位操作。