fluttercanvasflutter-layoutflutter-canvas

Problem containing flutter widget created with Custom Painter inside a box and also problem with zooming and panning the widget


I have created this districts map view widget with Custom Painter. I multiple paths and drew the paths using canvas as:



class MyPainter extends CustomPainter {
  Function(String) setState;
  final BuildContext context;

  MyPainter(this.context, this.setState);

  @override
  void paint(Canvas _canvas, Size size) {
    TouchyCanvas canvas = TouchyCanvas(context, _canvas);

    // _canvas.translate(0, 0);

    districtMapData.forEach((e) {
      var _path = parseSvgPathData(e['shape'].toString());

      canvas.drawPath(
          _path,
          Paint()
            ..color = Colors.black
            ..strokeWidth = 200
            ..style = PaintingStyle.fill, onTapDown: (a) {
        print("pressed");
        print(e['name']);
      }, onTapUp: (a) {
        print("pressed up");
      });
    });
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}


I am using path_drawing library to get the Path from svg path. I am using touchable library to make each path clickable in the canvas.

The first problem is that I cannot fit the custom paint widget in the Container I have created. The custom painted widget always goes out of bound of the width. The second problem is that that I cannot implement both double tap on zoom and pinch to zoom. I tried zoom_widget which allows double tap but cannot pan and pinch. I have also tried flutter's inbuilt InteractiveViewer but it does not seem to work with my code.


import 'package:flutter/material.dart';
import 'dart:math';

import 'package:touchable/touchable.dart';
import 'package:zoom_widget/zoom_widget.dart';

class ZoomableMapView extends StatefulWidget {
  @override
  _ZoomableMapViewState createState() => _ZoomableMapViewState();
}

class _ZoomableMapViewState extends State<ZoomableMapView>
    with SingleTickerProviderStateMixin {
  Color color = Colors.pink;

  @override
  Widget build(BuildContext context) {
    final _width = MediaQuery.of(context).size.width;

    return Scaffold(
        body: SafeArea(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          color: Colors.red,
          child: AnimatedContainer(
              duration: Duration(seconds: 1),
              width: _width,
              height: 400,
              child:
                  // InteractiveViewer
                  Zoom(
                // minScale: 0.1,
                // maxScale: 5,
                // alignPanAxis: false,

                maxZoomHeight: 1000,
                maxZoomWidth: 1000,
                initZoom: 0.1,
                // centerOnScale: false,
                child: Transform.rotate(
                  angle: -pi / 8,
                  child: CanvasTouchDetector(
                    builder: (context) {
                      return CustomPaint(
                        painter: MyPainter(context, (String circleColor) {}),
                      );
                    },
                  ),
                ),
              )),
        ),
      ),
    ));
  }
}

Here is the shape data used for canvas

Screenshot of the current implemenation


Solution

  • I had problem panning and pinching with zoom widget because I was also using touchable library for making canvas paths clickable. touchable library had its own implementation of pan gestures handling which were overriding the gestures of zoom widget. I had to fork and remove the pan gesture callbacks in the touchable library to make the pinch and pan zoom working.