Reputation: 790
I am using flutter_svg package to show svg picture in flutter but I want to be able to zoom into this picture without losing the svg properties of keeping the resolution, I have tried to use photo_view for zooming capabilities and flutter_svg_provider to use svg picture as image provider but it's not working properly.
So is there a way to be able to zoom and move freely in SVG picture in Flutter?
Upvotes: 4
Views: 1093
Reputation: 6735
To zoom and move freely in an SVG picture you can simply use InteractiveViewer
widget which is built in Flutter SDK itself and allows you to zoom and pan its child Widget. The minScale
and maxScale
properties control the minimum and maximum zoom levels. Also, do not forget to add the image asset to pubspec.yaml
1 in case you're using local svg
. If you're using network image, then you can use the SVG SvgPicture.network
function to load an SVG image from a URL. Also, you can use SvgPicture.asset
(like in the below example) or SvgPicture.file
if your SVG is located in your app's assets
or device storage, respectively.
// ...rest
body: Center(
child: InteractiveViewer(
minScale: 0.5,
maxScale: 4.0,
child: SvgPicture.asset(
"assets/images/sample.svg", // Replace with the name of your SVG file
height: 200,
),
),
),
Output:
Create an assets
folder at the root level of your project.
Inside the assets
folder, you can create subdirectories to organize your assets, such as an images
folder for image assets.
Place the svg
image inside the images
folder.
Open your pubspec.yaml
file and add the assets section under the flutter
key. Something like:
flutter:
uses-material-design: true
assets:
- assets/images/your_image.svg
Upvotes: 4
Reputation: 20098
You can use InteractiveViewer
to achieve what you want with custom animations.
class PinchZoomSvg extends StatefulWidget {
final String urlImage;
const PinchZoomSvg({
Key? key,
required this.urlImage,
}) : super(key: key);
@override
State<PinchZoomSvg> createState() => _PinchZoomSvgState();
}
class _PinchZoomSvgState extends State<PinchZoomSvg>
with SingleTickerProviderStateMixin {
late TransformationController controller;
late AnimationController animationController;
Animation<Matrix4>? animation;
final double minScale = 1;
final double maxScale = double.infinity;
@override
void initState() {
super.initState();
controller = TransformationController();
animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 200),
)
..addListener(() => controller.value = animation!.value)
..addStatusListener((status) {});
}
@override
void dispose() {
controller.dispose();
animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Center(
child: buildImage(),
);
Widget buildImage() => Builder(
builder: (context) => InteractiveViewer(
transformationController: controller,
clipBehavior: Clip.none,
panEnabled: false,
minScale: minScale,
maxScale: maxScale,
onInteractionStart: (details) {
if (details.pointerCount < 2) return;
animationController.stop();
},
onInteractionEnd: (details) {
// only executed if interaction ends with no fingers on screen
if (details.pointerCount != 1) return;
resetAnimation();
},
child: AspectRatio(
aspectRatio: 1,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SvgPicture.asset(
widget.urlImage,
fit: BoxFit.cover,
)),
),
),
);
void resetAnimation() {
animation = Matrix4Tween(
begin: controller.value,
end: Matrix4.identity(),
).animate(
CurvedAnimation(parent: animationController, curve: Curves.easeInOut),
);
animationController.forward(from: 0);
}
}
You can now use the widget whenever you want:
Center(
child: PinchZoomSvg(
urlImage: 'assets/logo.svg',
),
),
The code in this post was inspired by this YouTube video - please watch it (until minute 3:24) as it will explain the code in detail.
flutter_svg
.pubspec.yaml
.Upvotes: 2