Search code examples
flutterdartmapbox-gl

How to customise Map Symbols in Flutter MapboxGL?


I'm currently using Mapbox Flutter GL in my app and I'm trying to display various users as images.

This is currently working by getting locations and profile photos displaying them onto the map via addSymbols() as below:

void _setOnlineUserLocationsOnMap() async {
    for (User onlineUser in _onlineUsers) {
      Uint8List profilePhotoBytes = await getImage(onlineUser.photo!);
      // Uint8List markerImage = await loadMarkerImage();
      _mapController.addImage(onlineUser.username!, profilePhotoBytes);
    }

    List<SymbolOptions> symbols =
        _onlineUsers.map((User? onlineUser) {
      if (onlineUser != null) {
        return SymbolOptions(
          geometry: LatLng(
              onlineUser.location!.latitude, onlineUser.location!.longitude),
          iconImage: onlineUser.username,
          iconSize: 0.2,
          draggable: false,
        );
      }
      return SymbolOptions();
    }).toList();

    _mapController.addSymbols(symbols);
  }

However, the limitations of the 'Symbol' is quite limited. The image shows as a square picture as that's how it was uploaded to the DB, however - I want to add more functionality around the symbol.

The main thing I'd like to do is turn the 'Symbol' into a widget which you can add ClipRect, boxDecoration, and possibly gesture recognisers.

Is this at all possible with the current version of Flutter-MapboxGL?


Solution

  • So, I figured out a way to go about this problem. The solution being a flutter pub called Screenshot.

    The overall package is a screens hotter for your app but you are able to choose what it is you'd like to take a screenshot of. This can be either a whole page, a portion of a page or even just a widget.

    The beauty of the package is that it has an ability to build a widget for you off the screen and screenshot it to return a Uint8List of bytes which correspond to the image.

    So, I build a widget with the border with a normal CircleAvatar widget in which you can pass other attributes, then take a screenshot of the widget and use that when adding to the Mapbox mapController via addImage()

    Here is an example of the util code that does this for you

    import 'package:screenshot/screenshot.dart';
    
    ScreenshotController screenshotController = ScreenshotController();
    
    // Reading bytes from a network image
    Future<Uint8List> getImageForUserMarker(
        String firstName, String lastName, String photoUrl) async {
      Uint8List imageBytes =
          await screenshotController.captureFromWidget(UserImageMarker(
        firstName: firstName,
        lastName: lastName,
        photoUrl: photoUrl,
      ));
      return imageBytes;
    }