5

I am using the google_maps_flutter: ^2.1.3 package in my Flutter project that I am currently developing and I want to show active regions on the map in the application. I tried to show the active regions on the map using polygons, but I couldn't paint the part outside of these regions a different color. Actually, exactly what I want on the map, everywhere will be gray (to be clear that it is not active), but some areas will be white (to be clear that it is active) surrounded by borders. You can understand exactly what I want by looking at the image below. In this way, there will be more than one active region on the map.

enter image description here

Note: As I mentioned before, I can get this image using polygons, but I cannot make the outside of the polygons gray.

Melik BOZKURT
  • 110
  • 12

2 Answers2

4

Polygon has a holes parameter which accepts a list of List<LatLng>. What you want to do is create one big polygon that covers the world (or viewport) and set that to be the background color. Then put your actual polygon(s) that you want to draw in the holes section to create a cutout:

Polygon maskedArea = new Polygon(
  fillColor: Colors.black.withOpacity(0.5),
  polygonId: new PolygonId('test'),
  holes: [<LatLng>[new LatLng(10, 10), new LatLng(40, 10), new LatLng(40, 40), new LatLng(10, 40)]],
  points: <LatLng>[new LatLng(0, 0), new LatLng(50, 0), new LatLng(50, 50), new LatLng(0, 50)]
);

If you're open to using plugins, there is also syncfusion_flutter_maps which seems to use a custom vector drawing solution to achieve a more robust result through the MapPolygonLayer.inverted constructor (I have not used this plugin myself but have used others from the developer and would anticipate no issues here).

enter image description here

Matt
  • 2,953
  • 3
  • 27
  • 46
  • Thanks for your answer. I tried to create one big polygon that covers the whole world but I couldn't. If you can show me how can I create that polygon without some silly borders from north pole to the south pole this could be accepted answer. But if I can't cover the whole world this solution doesn't work for me. – Melik BOZKURT Sep 14 '22 at 10:43
  • 2
    You will need to intelligently adjust those boundaries depending on where the user is looking (e.g. through the map controller's `getVisibleRegion()` method). This will prevent them from ever seeing borders if they happen to have an active region near the world seam. Depending on your application's needs you may also want to consider restricting the zoom level to keep the focus on the active area and prevent them from trying to view the whole world at once. – Matt Sep 15 '22 at 16:49
  • I know that edges of the holes will have the same style as the polygon borders but when I try to draw a polygon that covers the world a line from north pole to the south pole appears. To avoid this problem I have explained my solution. Yeah it is possible to cover all the world without a silly line and put holes with borders. Just check my answer. Thanks! – Melik BOZKURT Sep 20 '22 at 14:58
3

Based on Matt's answer, I came up with the exact solution. First, I couldn't draw a polygon that would cover the entire world, and instead I increased the polygon count to 2. I drew 2 polygons covering the whole world, from 0 to east and from 0 to west. I set the strokeWidth values to 0 so that these polygons do not draw lines from the north pole to the south pole. Later, I showed the active areas in holes, but because my strokeWidth value was 0, the border line did not occur. To avoid this event, I created a new polygon with the fillColor value Colors.transparent and the same coordinates, and set the strokeWidth value to 2.

My sample codes are as follows:

 polygon.add(
      Polygon(
        fillColor: Colors.black.withOpacity(0.5),
        polygonId: const PolygonId('test'),
        holes: [if (pointsFromService.length != 0) pointsFromService],
        points: const [
          LatLng(-89, 0),
          LatLng(89, 0),
          LatLng(89, 179.999),
          LatLng(-89, 179.999),
        ],
        visible: true,
        geodesic: false,
        strokeWidth: 0,
      ),
    );
    polygon.add(
      Polygon(
        fillColor: Colors.black.withOpacity(0.5),
        polygonId: const PolygonId('test2'),
        points: const [
          LatLng(-89.9, 0),
          LatLng(89.9, 0),
          LatLng(89.9, -179.999),
          LatLng(-89.9, -179.999),
        ],
        visible: true,
        geodesic: false,
        strokeWidth: 0,
      ),
    );
    if (pointsFromService.length != 0) {
      polygon.add(
        Polygon(
          fillColor: Colors.transparent,
          strokeColor: primaryColor,
          polygonId: const PolygonId('test3'),
          points: pointsFromService,
          visible: true,
          geodesic: false,
          strokeWidth: 2,
        ),
      );
    }
  }

The result is as follows: (Note that the gray area covers the whole world)

enter image description here

Melik BOZKURT
  • 110
  • 12
  • 1
    Oh, awesome! I'm glad you found a way around the border issue that didn't involve moving the bounds; that's an interesting solution. – Matt Sep 20 '22 at 15:25