0

So I have this world map SVG from here: https://mapsvg.com/maps/world. I'm trying to copy the individual path data of the map and store them into a multi-line string. Then splitting that string by a new line.
Then for each data string, I'm converting the data string to the path object and tried to draw it, but it doesn't draw anything. Here is the sample code:

import 'package:flutter/material.dart';
import 'package:path_drawing/path_drawing.dart';
import 'package:touchable/touchable.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CanvasTouchDetector(
        gesturesToOverride: const [GestureType.onTapUp],
        builder: (context) {
          return CustomPaint(
            size: const Size(double.infinity, double.infinity),
            painter: MyPainter(context),
          );
        },
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  final BuildContext context;
  MyPainter(this.context);

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

    final List<String> paths =
        '''m 479.68275,331.6274 -0.077,0.025 -0.258,0.155 -0.147,0.054 -0.134,0.027 -0.105,-0.011 -0.058,-0.091 0.006,-0.139 -0.024,-0.124 -0.02,-0.067 0.038,-0.181 0.086,-0.097 0.119,-0.08 0.188,0.029 0.398,0.116 0.083,0.109 10e-4,0.072 -0.073,0.119 z'''
            .split('\n');

    // drawing the paths
    for (int i = 0; i < paths.length; i++) {
      Path path = parseSvgPathData(paths[i]);

      touchyCanvas.drawPath(
        path,
        Paint()
          ..color = Colors.red
          ..strokeWidth = 2,
        onTapUp: (details) {
          print('clicked');
        },
      );
    }
  }

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

Note: The path data inside the string is of Andorra.

I'm trying to follow this answer here: https://stackoverflow.com/a/60947105/11283915. When I use the data string from this answer, it draws fine but doesn't work with the data string that I'm trying to use from the SVG.

dipansh
  • 331
  • 3
  • 15

1 Answers1

0

Setting the size of the custom painter same as the viewbox of the SVG made the path appear on the painter. e.g. I had a SVG with viewbox="0 0 2000 857" so I set the custom painter size to Size(2000, MediaQuery.of(context).size.hieght) setting the height to the device height only because my device height was pretty close to the height defined in the viewbox.

The below code works:

import 'package:flutter/material.dart';
import 'package:path_drawing/path_drawing.dart';
import 'package:touchable/touchable.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: InteractiveViewer(
          child: CanvasTouchDetector(
            gesturesToOverride: const [GestureType.onTapUp],
            builder: (context) {
              return CustomPaint(
                size: const Size(2000, double.infinity),
                painter: MyPainter(context),
              );
            },
          ),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  final BuildContext context;
  MyPainter(this.context);

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

    final Map<String, String> mapData = {
      'af':
          'M1383 261.6l1.5 1.8-2.9 0.8-2.4 1.1-5.9 0.8-5.3 1.3-2.4 2.8 1.9 2.7 1.4 3.2-2 2.7 0.8 2.5-0.9 2.3-5.2-0.2 3.1 4.2-3.1 1.7-1.4 3.8 1.1 3.9-1.8 1.8-2.1-0.6-4 0.9-0.2 1.7-4.1 0-2.3 3.7 0.8 5.4-6.6 2.7-3.9-0.6-0.9 1.4-3.4-0.8-5.3 1-9.6-3.3 3.9-5.8-1.1-4.1-4.3-1.1-1.2-4.1-2.7-5.1 1.6-3.5-2.5-1 0.5-4.7 0.6-8 5.9 2.5 3.9-0.9 0.4-2.9 4-0.9 2.6-2-0.2-5.1 4.2-1.3 0.3-2.2 2.9 1.7 1.6 0.2 3 0 4.3 1.4 1.8 0.7 3.4-2 2.1 1.2 0.9-2.9 3.2 0.1 0.6-0.9-0.2-2.6 1.7-2.2 3.3 1.4-0.1 2 1.7 0.3 0.9 5.4 2.7 2.1 1.5-1.4 2.2-0.6 2.5-2.9 3.8 0.5 5.4 0z',
    };

    // drawing the paths
    for (String key in mapData.keys) {
      Path path = parseSvgPathData(mapData[key]!);

      touchyCanvas.drawPath(
        path,
        Paint()
          ..color = Colors.red
          ..strokeWidth = 2,
        onTapUp: (details) {
          print('clicked $key');
        },
      );
    }
  }

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

To see the path drawn, I just need to scroll the screen. In case if you want to limit the area in which the SVG is drawn, follow this: https://stackoverflow.com/a/60947105/11283915

dipansh
  • 331
  • 3
  • 15