更新:正如@rdnobrega 善意解释的那样,这无论如何都不是一个理想的解决方案。它仅在唯一转换的矩阵是比例时才有效,并且会与其他转换中断。我不是数学专家或 Matrix4 专家,所以下面的解决方案需要您自担风险。
我遇到了同样的问题,花了一段时间才找到解决方案。
在 Flutter 的 Transform.scale source 中挖掘了一下之后,我们发现了这行代码:
transform = Matrix4.diagonal3Values(scale, scale, 1.0)
它使用您在onMatrixUpdate 中收到的Matrix4 的对角线值。所以它需要x 来自第一个 Vector4,y 来自第二个,z 来自第三个。 (据我所知,第四个是固定的)。所以这些是你需要限制的值。在这个例子中,我制作了一个小的 _minMax 方法,它在相关时将比例限制为相关的最小值/最大值(可以将它们传递给 null 以忽略限制的任一侧)。
我用这个来限制规模:
typedef MathF<T extends num> = T Function(T, T);
typedef VFn = Vector4 Function(double x, double y, double z, double w);
double _minMax(num _min, num _max, num actual) {
if (_min == null && _max == null) {
return actual.toDouble();
}
if (_min == null) {
return min(_max.toDouble(), actual.toDouble());
}
if (_max == null) {
return max(_min.toDouble(), actual.toDouble());
}
return min(_max.toDouble(), max(_min.toDouble(), actual.toDouble()));
}
// ... ... ...
onMatrixUpdate: (Matrix4 m, Matrix4 tm, Matrix4 sm, Matrix4 rm) {
var finalM = Matrix4.copy(m);
Map<int, VFn> colmap = {
0: (x, y, z, w) {
x = _minMax(widget.minScale, widget.maxScale, x);
return Vector4(x, y, z, w);
},
1: (x, y, z, w) {
y = _minMax(widget.minScale, widget.maxScale, y);
return Vector4(x, y, z, w);
},
2: (x, y, z, w) {
z = _minMax(widget.minScale, widget.maxScale, z);
return Vector4(x, y, z, w);
},
};
for (var col in colmap.keys) {
var oldCol = m.getColumn(col);
var colD = colmap[col];
if (colD != null) {
finalM.setColumn(col, colD(oldCol.x, oldCol.y, oldCol.z, oldCol.w));
}
}
setState(() {
matrix = finalM;
});
},