ios – How one can add circle annotation to Flutter mapbox

ios – How one can add circle annotation to Flutter mapbox


I am making a Flutter web page and I need to have a Mapbox widget that exhibits a highlighted circle across the consumer’s location. And there is a slider outdoors the map that may alter the radius of the circle. The circle dimension also needs to be relative to the zoom degree, so if I zoom all the way in which out, the dimensions does not turn out to be actually massive.

Proper now, my code works for adjusting the radius, however the map flashes each time the slider strikes. The zoom can be arduous to make use of, as a result of the zoom degree is reset each time I transfer the slider.

I additionally get an error message each time I transfer the slider

[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter.ScaleBarSettingsInterface.updateSettings.2"., null, null)
#0      ScaleBarSettingsInterface.updateSettings (package deal:mapbox_maps_flutter/src/pigeons/settings.dart:1138:7)

#1      _AreaCaptureScreenState._onMapCreated (package deal:sighttrack/screens/seize/area_capture.dart:37:5)

flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CameraManager.getCameraState.2"., null, null)
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CameraManager.getCameraState.2"., null, null)
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CircleAnnotationMessenger.deleteAll.1"., null, null)
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CircleAnnotationMessenger.deleteAll.1"., null, null)
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CameraManager.getCameraState.2"., null, null)
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CircleAnnotationMessenger.deleteAll.1"., null, null)
flutter: Error updating circle: PlatformException(channel-error, Unable to determine connection on channel: "dev.flutter.pigeon.mapbox_maps_flutter._CircleAnnotationMessenger.deleteAll.1"., null, null)
flutter: Error updating circle: Null examine operator used on a null worth
flutter: Error updating circle: Null examine operator used on a null worth

Right here is the web page code (API keys are arrange in predominant.dart)

import 'dart:math' as math;

import 'package deal:flutter/materials.dart';
import 'package deal:mapbox_maps_flutter/mapbox_maps_flutter.dart';
import 'package deal:geolocator/geolocator.dart' as geo;

class AreaCaptureScreen extends StatefulWidget {
  const AreaCaptureScreen({tremendous.key});

  @override
  State createState() => _AreaCaptureScreenState();
}

class _AreaCaptureScreenState extends State {
  MapboxMap? _mapboxMap;
  CircleAnnotationManager? _circleManager;
  CircleAnnotation? _circleAnnotation;
  bool _isDisposed = false;
  Level? _centerPoint;
  double _radiusMeters = 300.0; // Non-final

  @override
  void dispose() {
    _isDisposed = true;
    tremendous.dispose();
  }

  void _onMapCreated(MapboxMap mapboxMap) async {
    if (_isDisposed || !mounted) return;
    _mapboxMap = mapboxMap;

    // Disguise UI components
    await mapboxMap.emblem.updateSettings(LogoSettings(enabled: false));
    await mapboxMap.attribution.updateSettings(
      AttributionSettings(enabled: false),
    );
    await mapboxMap.scaleBar.updateSettings(ScaleBarSettings(enabled: false));

    // Allow location puck
    await _mapboxMap!.location.updateSettings(
      LocationComponentSettings(
        enabled: true,
        pulsingEnabled: true,
        puckBearingEnabled: true,
      ),
    );

    strive  catch (e) {
      debugPrint('Error establishing map: $e');
    }
  }

  Future _updateCircle() async {
    if (_mapboxMap == null || _centerPoint == null || _isDisposed || !mounted)
      return;

    strive {
      // Initialize supervisor if not already set
      _circleManager ??=
          await _mapboxMap!.annotations.createCircleAnnotationManager();

      // Calculate pixel radius
      closing cameraState = await _mapboxMap!.getCameraState();
      closing double groundResolution =
          156543.03392 *
          math.cos(_centerPoint!.coordinates.lat * math.pi / 180) /
          math.pow(2, cameraState.zoom);
      closing double pixelRadius = _radiusMeters / groundResolution;

      // All the time create a brand new annotation to keep away from ID points
      await _circleManager!.deleteAll(); // Clear current annotations
      _circleAnnotation = await _circleManager!.create(
        CircleAnnotationOptions(
          geometry: _centerPoint!,
          circleRadius: pixelRadius,
          circleColor: Shade(0xFF33AFFF).toARGB32(),
          circleOpacity: 0.3,
          circleStrokeWidth: 1.5,
          circleStrokeColor: Shade(0xFF0077FF).toARGB32(),
        ),
      );
    } catch (e) {
      debugPrint('Error updating circle: $e');
      // Recreate supervisor on error to deal with potential corruption
      _circleManager = null;
      if (mounted && !_isDisposed) {
        _circleManager =
            await _mapboxMap!.annotations.createCircleAnnotationManager();
        await _updateCircle(); // Retry as soon as
      }
    }
  }

  Future _determinePosition() async {
    bool serviceEnabled = await geo.Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) throw Exception('Location providers are disabled.');

    geo.LocationPermission permission = await geo.Geolocator.checkPermission();
    if (permission == geo.LocationPermission.denied) {
      permission = await geo.Geolocator.requestPermission();
      if (permission == geo.LocationPermission.denied) {
        throw Exception('Location permissions are denied.');
      }
    }
    if (permission == geo.LocationPermission.deniedForever) {
      throw Exception('Location permissions are completely denied.');
    }

    return await geo.Geolocator.getCurrentPosition();
  }

  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      backgroundColor: Colours.black,
      appBar: AppBar(
        backgroundColor: Colours.clear,
        foregroundColor: Colours.white,
      ),
      physique: SafeArea(
        baby: Padding(
          padding: const EdgeInsets.all(16.0),
          baby: Column(
            youngsters: [
              Container(
                height: 300,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                ),
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(10),
                  child: MapWidget(
                    styleUri:
                        '',
                    cameraOptions: CameraOptions(
                      center: Point(coordinates: Position(-122.4194, 37.7749)),
                      zoom: 15.0,
                    ),
                    onMapCreated: _onMapCreated,
                    onCameraChangeListener: (event) {
                      if (_circleAnnotation != null) {
                        _updateCircle();
                      }
                    },
                    key: UniqueKey(),
                  ),
                ),
              ),
              Slider(
                value: _radiusMeters,
                min: 100.0,
                max: 1000.0,
                onChanged: (newRadius) {
                  setState(() {
                    _radiusMeters = newRadius;
                    _updateCircle();
                  });
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *