可容纳一个子组件,可以通过一个4*4的变换矩阵对子组件进行变换。
相关组件
Container
斜切变换skew
<br />斜切x由R0C1数控制,入参为弧度值,表示斜切角度<br />斜切y由R1C0数控制,入参为弧度值,表示斜切角度<br />![174.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589462243860-8d483713-b703-4601-8f12-a0d6e9e758ec.gif#align=left&display=inline&height=410&margin=%5Bobject%20Object%5D&name=174.gif&originHeight=410&originWidth=786&size=3547439&status=done&style=none&width=786)
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'matrix4_shower.dart';
class SkewTransform extends StatefulWidget {
@override
_SkewTransformState createState() => _SkewTransformState();
}
class _SkewTransformState extends State<SkewTransform> {
Matrix4 _m4;
double _alpha = 0;
double _beta = 0;
@override
void initState() {
_m4 = Matrix4.identity();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTransform(), Matrix4Shower(_m4)],
),
_buildSliders()
],
);
}
Widget _buildTransform() {
_m4 = Matrix4.skew(_alpha, _beta);
return Transform(
transform: _m4,
child: Container(
color: Colors.cyanAccent,
width: 100,
height: 100,
child: Image.asset(
'assets/images/wy_300x200.jpg',
fit: BoxFit.cover,
)),
);
}
Widget _buildSliders() => Column(
children: <Widget>[
Slider(
min: -pi,
max: pi,
value: _alpha,
divisions: 360,
label: 'alpha:' + (_alpha * 180 / pi).toStringAsFixed(1) + "°",
onChanged: (v) {
setState(() {
_alpha = v;
});
}),
Slider(
min: -pi,
max: pi,
value: _beta,
divisions: 360,
label: 'beta:' + (_beta * 180 / pi).toStringAsFixed(1) + "°",
onChanged: (v) {
setState(() {
_beta = v;
});
})
],
);
}
平移变换translationValues
<br />平移x由R0C3数控制,入参为数值,表示平移长度<br />平移y由R1C3数控制,入参为数值,表示平移长度<br />平移z由R2C3数控制,入参为数值,表示平移长度<br />![175.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589462318124-8b52d273-6ea5-48e1-9659-6d8325f92ec6.gif#align=left&display=inline&height=616&margin=%5Bobject%20Object%5D&name=175.gif&originHeight=616&originWidth=786&size=3593192&status=done&style=none&width=786)
import 'package:flutter/material.dart';
import 'matrix4_shower.dart';
class TranslationTransform extends StatefulWidget {
@override
_TranslationTransformState createState() => _TranslationTransformState();
}
class _TranslationTransformState extends State<TranslationTransform> {
Matrix4 _m4;
double _x = 0;
double _y = 0;
double _z = 0;
@override
void initState() {
_m4 = Matrix4.identity();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTransform(), Matrix4Shower(_m4)],
),
_buildSliders()
],
);
}
Widget _buildTransform() {
_m4 = Matrix4.translationValues(_x, _y, _z);
return Transform(
transform: _m4,
child: Container(
color: Colors.cyanAccent,
width: 100,
height: 100,
child: Image.asset(
'assets/images/wy_300x200.jpg',
fit: BoxFit.cover,
)),
);
}
Widget _buildSliders() => Column(
children: <Widget>[
Slider(
min: -100,
max: 100,
value: _x,
divisions: 360,
label: 'x:${_x.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_x = v;
});
}),
Slider(
min: -100,
max: 100,
value: _y,
divisions: 360,
label: 'y:${_y.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_y = v;
});
}),
Slider(
min: -100,
max: 100,
value: _z,
divisions: 360,
label: 'z:${_z.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_z = v;
});
})
],
);
}
缩放变换diagonal3Values
<br />缩放x由R0C0数控制,入参为数值,表示缩放分率<br />缩放y由R1C2数控制,入参为数值,表示缩放分率<br />缩放z由R2C2数控制,入参为数值,表示缩放分率<br />![176.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589462374327-af67aff9-33d1-488a-a1f7-579ea178947f.gif#align=left&display=inline&height=522&margin=%5Bobject%20Object%5D&name=176.gif&originHeight=522&originWidth=786&size=2188726&status=done&style=none&width=786)
import 'package:flutter/material.dart';
import 'matrix4_shower.dart';
class ScaleTransform extends StatefulWidget {
@override
_ScaleTransformState createState() => _ScaleTransformState();
}
class _ScaleTransformState extends State<ScaleTransform> {
Matrix4 _m4;
double _x = 1.0;
double _y = 1.0;
double _z = 1.0;
@override
void initState() {
_m4 = Matrix4.identity();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTransform(), Matrix4Shower(_m4)],
),
_buildSliders()
],
);
}
Widget _buildTransform() {
_m4 = Matrix4.diagonal3Values(_x, _y, _z);
return Transform(
transform: _m4,
child: Container(
color: Colors.cyanAccent,
width: 100,
height: 100,
child: Image.asset(
'assets/images/wy_300x200.jpg',
fit: BoxFit.cover,
)),
);
}
Widget _buildSliders() => Column(
children: <Widget>[
Slider(
min: -2,
max: 2,
value: _x,
divisions: 360,
label: 'x:${_x.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_x = v;
});
}),
Slider(
min: -2,
max: 2,
value: _y,
divisions: 360,
label: 'y:${_y.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_y = v;
});
}),
Slider(
min: -2,
max: 2,
value: _z,
divisions: 360,
label: 'z:${_z.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_z = v;
});
})
],
);
}
旋转变换rotation
<br />x旋转由R1C1、R1C2、R2C1、R2C2控制,入参表示弧度<br />y旋转由R0C0、R0C2、R2C0、R2C2控制,入参表示弧度<br />z旋转由R0C0、R0C1、R1C0、R1C1控制,<br />![177.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589462430534-e7ad9d64-f1b3-4e22-be1d-77b02c2ecda2.gif#align=left&display=inline&height=436&margin=%5Bobject%20Object%5D&name=177.gif&originHeight=436&originWidth=786&size=3119049&status=done&style=none&width=786)
import 'dart:math';
import 'package:flutter/material.dart';
import 'matrix4_shower.dart';
class RotateTransform extends StatefulWidget {
@override
_RotateTransformState createState() => _RotateTransformState();
}
class _RotateTransformState extends State<RotateTransform> {
Matrix4 _m4;
double _x = 0;
int _rotateFlag = 1;
@override
void initState() {
_m4 = Matrix4.identity();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[_buildTransform(), Matrix4Shower(_m4)],
),
_buildSliders()
],
);
}
Widget _buildTransform() {
if (_rotateFlag == 1) {
_m4 = Matrix4.rotationX(_x);
} else if (_rotateFlag == 2) {
_m4 = Matrix4.rotationY(_x);
} else {
_m4 = Matrix4.rotationZ(_x);
}
return Transform(
transform: _m4,
child: Container(
color: Colors.cyanAccent,
width: 100,
height: 100,
child: Image.asset(
'assets/images/wy_300x200.jpg',
fit: BoxFit.cover,
)),
);
}
final Map<int, String> map = {
1: 'rotationX',
2: 'rotationY',
3: 'rotationZ',
};
Widget _buildSliders() => Column(
children: <Widget>[
Wrap(
children: map.keys.map((key) => _buildChild(key)).toList(),
),
Slider(
min: -pi,
max: pi,
value: _x,
divisions: 360,
label: 'x:${_x.toStringAsFixed(1)}',
onChanged: (v) {
setState(() {
_x = v;
});
}),
],
);
Padding _buildChild(int key) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: FilterChip(
selectedColor: Colors.orange.withAlpha(55),
selectedShadowColor: Colors.blue,
shadowColor: Colors.orangeAccent,
pressElevation: 5,
elevation: 3,
avatar: CircleAvatar(child: Text(key.toString())),
label: Text(map[key]),
selected: _rotateFlag == key,
onSelected: (bool value) {
print(map[key]);
setState(() {
_x = 0;
if (value) {
_rotateFlag = key;
}
});
},
),
);
}
}
透视变换rotation
<br />由R3C1、R3C2、R3C3控制透视<br />![178.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589462487281-c244e73c-cb07-456c-897d-2ef8405c4f53.gif#align=left&display=inline&height=436&margin=%5Bobject%20Object%5D&name=178.gif&originHeight=436&originWidth=786&size=2849759&status=done&style=none&width=786)
import 'dart:math';
import 'package:flutter/material.dart';
class R3C2 extends StatefulWidget {
@override
_R3C2State createState() => _R3C2State();
}
class _R3C2State extends State<R3C2> {
Matrix4 _m4;
double _value = 0;
double _rad = 0;
@override
Widget build(BuildContext context) {
_m4 = Matrix4.identity()
// ..setEntry(3, 0, _value) // x
// ..setEntry(3, 1, _value)// y
..setEntry(3, 2, _value) // z
..rotateY(_rad)
// ..rotateX(_rad)
;
return Column(
children: <Widget>[
Transform(
transform: _m4,
child: Container(
color: Colors.cyanAccent,
width: 100,
height: 100,
child: Image.asset(
'assets/images/wy_300x200.jpg',
fit: BoxFit.cover,
)),
),
_buildSliders()
],
);
}
Widget _buildSliders() => Column(
children: <Widget>[
Slider(
min: -0.01,
max: 0.01,
value: _value,
divisions: 360,
label: 'x:${_value.toStringAsFixed(5)}',
onChanged: (v) {
setState(() {
_value = v;
});
}),
Slider(
min: -pi,
max: pi,
value: _rad,
divisions: 360,
label: '角度:' + (_rad * 180 / pi).toStringAsFixed(1) + "°",
onChanged: (v) {
setState(() {
_rad = v;
});
}),
],
);
}