如何平移和缩放图像?
How do I pan and zoom an image?
我正在尝试获取一些基本的图像平移和缩放功能。无状态版本可以显示图像(通过 Transform 旋转 180 度)并且 Scale 事件显示在日志中,仅此而已。
GestureDetector
是获取 pan/pinch/spread 事件的正确小部件吗?我应该查看变换、动画,还是只修改 Image
小部件内的字段?
无状态版本
// Wraps an Image widget to provide pan and zoom functionality.
class InteractiveImage extends StatelessWidget {
InteractiveImage(this._image, {Key key}) : super(key: key);
final Image _image;
@override
Widget build(BuildContext context) {
return new Center(
child: new GestureDetector(
onScaleStart: (ScaleStartDetails details) => print(details),
onScaleUpdate: (ScaleUpdateDetails details) => print(details),
onScaleEnd: (ScaleEndDetails details) => print(details),
child: new Transform(
transform: new Matrix4.rotationZ(math.PI),
alignment: FractionalOffset.center,
child: _image,
),
),
);
}
}
有状态版本(不起作用)
// Wraps an Image widget to provide pan and zoom functionality.
class InteractiveImage extends StatefulWidget {
InteractiveImage(this._image, {Key key}) : super(key: key);
final Image _image;
@override
_InteractiveImageState createState() => new _InteractiveImageState(_image);
}
class _InteractiveImageState extends State<InteractiveImage> {
_InteractiveImageState(this._image);
final Image _image;
@override
Widget build(BuildContext context) {
setState(() => print("STATE SET\n"));
return new GestureDetector(
onScaleStart: (ScaleStartDetails details) => print(details),
onScaleUpdate: (ScaleUpdateDetails details) => print(details),
onScaleEnd: (ScaleEndDetails details) => print(details),
child: new Transform(
transform: new Matrix4.rotationZ(math.PI),
alignment: FractionalOffset.center,
child: _image,
),
);
}
}
更新(库解)
使用https://pub.dartlang.org/packages/zoomable_image
(也许可以帮我添加物理和弹性边缘?)
我不确定 "doesn't work" 是什么意思,但您的方向是对的。
查看 https://github.com/flutter/flutter/blob/master/examples/layers/widgets/gestures.dart 可平移、收缩和缩放的小部件的工作示例。
根据问题中的代码并在 Collin 的回答的鼓舞下,这就是我想出的:
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart';
class InteractiveImage extends StatefulWidget {
InteractiveImage(this.image, {Key key}) : super(key: key);
final Image image;
@override
_InteractiveImageState createState() => new _InteractiveImageState();
}
class _InteractiveImageState extends State<InteractiveImage> {
_InteractiveImageState();
double _scale = 1.0;
double _previousScale = null;
@override
Widget build(BuildContext context) {
setState(() => print("STATE SET\n"));
return new GestureDetector(
onScaleStart: (ScaleStartDetails details) {
print(details);
// Does this need to go into setState, too?
// We are only saving the scale from before the zooming started
// for later - this does not affect the rendering...
_previousScale = _scale;
},
onScaleUpdate: (ScaleUpdateDetails details) {
print(details);
setState(() => _scale = _previousScale * details.scale);
},
onScaleEnd: (ScaleEndDetails details) {
print(details);
// See comment above
_previousScale = null;
},
child: new Transform(
transform: new Matrix4.diagonal3(new Vector3(_scale, _scale, _scale)),
alignment: FractionalOffset.center,
child: widget.image,
),
);
}
}
虽然看起来可行,但如果能得到 Flutter 团队内部人员的确认或更正,那就太好了。
(此外,这仅允许缩放。未实现平移。)
编辑: 编辑以反映 and his 。但请注意,关于私有 setState()
和不会立即影响渲染的私有字段,仍然存在一个悬而未决的问题。
您可以使用 Flutter 开箱即用的 InteractiveViewer。
@override
Widget build(BuildContext context) {
return Center(
child: InteractiveViewer(
panEnabled: false, // Set it to false
boundaryMargin: EdgeInsets.all(100),
minScale: 0.5,
maxScale: 2,
child: Image.asset(
'your_image_asset',
width: 200,
height: 200,
fit: BoxFit.cover,
),
),
);
}
我正在尝试获取一些基本的图像平移和缩放功能。无状态版本可以显示图像(通过 Transform 旋转 180 度)并且 Scale 事件显示在日志中,仅此而已。
GestureDetector
是获取 pan/pinch/spread 事件的正确小部件吗?我应该查看变换、动画,还是只修改 Image
小部件内的字段?
无状态版本
// Wraps an Image widget to provide pan and zoom functionality.
class InteractiveImage extends StatelessWidget {
InteractiveImage(this._image, {Key key}) : super(key: key);
final Image _image;
@override
Widget build(BuildContext context) {
return new Center(
child: new GestureDetector(
onScaleStart: (ScaleStartDetails details) => print(details),
onScaleUpdate: (ScaleUpdateDetails details) => print(details),
onScaleEnd: (ScaleEndDetails details) => print(details),
child: new Transform(
transform: new Matrix4.rotationZ(math.PI),
alignment: FractionalOffset.center,
child: _image,
),
),
);
}
}
有状态版本(不起作用)
// Wraps an Image widget to provide pan and zoom functionality.
class InteractiveImage extends StatefulWidget {
InteractiveImage(this._image, {Key key}) : super(key: key);
final Image _image;
@override
_InteractiveImageState createState() => new _InteractiveImageState(_image);
}
class _InteractiveImageState extends State<InteractiveImage> {
_InteractiveImageState(this._image);
final Image _image;
@override
Widget build(BuildContext context) {
setState(() => print("STATE SET\n"));
return new GestureDetector(
onScaleStart: (ScaleStartDetails details) => print(details),
onScaleUpdate: (ScaleUpdateDetails details) => print(details),
onScaleEnd: (ScaleEndDetails details) => print(details),
child: new Transform(
transform: new Matrix4.rotationZ(math.PI),
alignment: FractionalOffset.center,
child: _image,
),
);
}
}
更新(库解)
使用https://pub.dartlang.org/packages/zoomable_image
(也许可以帮我添加物理和弹性边缘?)
我不确定 "doesn't work" 是什么意思,但您的方向是对的。
查看 https://github.com/flutter/flutter/blob/master/examples/layers/widgets/gestures.dart 可平移、收缩和缩放的小部件的工作示例。
根据问题中的代码并在 Collin 的回答的鼓舞下,这就是我想出的:
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart';
class InteractiveImage extends StatefulWidget {
InteractiveImage(this.image, {Key key}) : super(key: key);
final Image image;
@override
_InteractiveImageState createState() => new _InteractiveImageState();
}
class _InteractiveImageState extends State<InteractiveImage> {
_InteractiveImageState();
double _scale = 1.0;
double _previousScale = null;
@override
Widget build(BuildContext context) {
setState(() => print("STATE SET\n"));
return new GestureDetector(
onScaleStart: (ScaleStartDetails details) {
print(details);
// Does this need to go into setState, too?
// We are only saving the scale from before the zooming started
// for later - this does not affect the rendering...
_previousScale = _scale;
},
onScaleUpdate: (ScaleUpdateDetails details) {
print(details);
setState(() => _scale = _previousScale * details.scale);
},
onScaleEnd: (ScaleEndDetails details) {
print(details);
// See comment above
_previousScale = null;
},
child: new Transform(
transform: new Matrix4.diagonal3(new Vector3(_scale, _scale, _scale)),
alignment: FractionalOffset.center,
child: widget.image,
),
);
}
}
虽然看起来可行,但如果能得到 Flutter 团队内部人员的确认或更正,那就太好了。
(此外,这仅允许缩放。未实现平移。)
编辑: 编辑以反映 setState()
和不会立即影响渲染的私有字段,仍然存在一个悬而未决的问题。
您可以使用 Flutter 开箱即用的 InteractiveViewer。
@override
Widget build(BuildContext context) {
return Center(
child: InteractiveViewer(
panEnabled: false, // Set it to false
boundaryMargin: EdgeInsets.all(100),
minScale: 0.5,
maxScale: 2,
child: Image.asset(
'your_image_asset',
width: 200,
height: 200,
fit: BoxFit.cover,
),
),
);
}