flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
162.2k stars 26.64k forks source link

google_maps_flutter web displays marker on map in desktop browser, but not displays marker in mobile browser #147522

Open kalpeshmayani opened 2 weeks ago

kalpeshmayani commented 2 weeks ago

Steps to reproduce

google_maps_flutter web displays marker on map in desktop browser, but not displays marker in mobile browser

Expected results

markers should display in both browsers

Actual results

markers on map displays only on desktop browser but not in mobile browser

Code sample

Code sample ```dart import 'dart:async'; import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:venziappweb/common/const.dart'; import 'package:venziappweb/common/utils.dart'; import '../../common/size_config.dart'; class EventMapWidget extends StatefulWidget { EventMapWidget({ Key? key, required this.eventLocation, required this.mapStyle, required this.duration, }) : super(key: key); final Position eventLocation; final String mapStyle; final String duration; @override _EventMapWidgetState createState() => _EventMapWidgetState(); } class _EventMapWidgetState extends State { final Completer _controller = Completer(); late Position _eventLocation; late String _mapStyle; Set _markers = {}; Set _circles = {}; Map _polylines = {}; late String _duration; @override void initState() { super.initState(); log("--- ${widget.eventLocation.toString()}"); _eventLocation = widget.eventLocation; _mapStyle = widget.mapStyle; _duration = widget.duration; } @override void didUpdateWidget(EventMapWidget oldWidget) { _duration = widget.duration; super.didUpdateWidget(oldWidget); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return ClipRRect( borderRadius: BorderRadius.all( Radius.circular(SizeConfig.getSize(5)), ), child: AbsorbPointer( absorbing: true, // set true to disable user interaction child: Stack( children: [ Positioned( child: GoogleMap( initialCameraPosition: const CameraPosition(target: LatLng(0.0, 0.0)), myLocationButtonEnabled: false, zoomGesturesEnabled: false, zoomControlsEnabled: false, rotateGesturesEnabled: false, scrollGesturesEnabled: false, tiltGesturesEnabled: false, circles: Set.from(_circles), markers: Set.from(_markers), polylines: Set.of(_polylines.values), gestureRecognizers: Set() ..add(Factory( () => PanGestureRecognizer())) ..add(Factory( () => ScaleGestureRecognizer())) ..add(Factory( () => TapGestureRecognizer())) ..add(Factory( () => VerticalDragGestureRecognizer())) ..add(Factory( () => HorizontalDragGestureRecognizer())) ..add(Factory( () => EagerGestureRecognizer())), onMapCreated: (GoogleMapController controller) async { _controller.complete(controller); _showLocationOnMap(context); }, ), ), Positioned( bottom: 0, child: Container( width: SizeConfig.getSize(182), height: SizeConfig.getSize(44.2), alignment: Alignment.center, padding: EdgeInsets.fromLTRB( SizeConfig.getSize(8), SizeConfig.getSize(15), SizeConfig.getSize(8), SizeConfig.getSize(8), ), decoration: const BoxDecoration( image: DecorationImage( image: AssetImage(walkDistanceBgImage), fit: BoxFit.cover, ), ), child: Row( children: [ Image.asset( clockIcon, width: SizeConfig.getSize(20.98), height: SizeConfig.getSize(20.98), ), SizedBox(width: SizeConfig.getSize(8)), Expanded( child: Text( _duration, style: GoogleFonts.montserrat( fontSize: SizeConfig.getSize(16), fontWeight: FontWeight.w400, color: colorWhiteWithOpacity87, ), ), ), ], ), ), ), ], ), ), ); } _showLocationOnMap(BuildContext context) async { final GoogleMapController controller = await _controller.future; controller.setMapStyle( await DefaultAssetBundle.of(context).loadString(_mapStyle)); // set marker for event address location Uint8List destinationIcon = await getBytesFromAsset(venziPinIcon, (SizeConfig.getSize(36)).ceil()); Marker destinationMarker = Marker( markerId: MarkerId('$_eventLocation'), position: LatLng( _eventLocation.latitude, _eventLocation.longitude, ), icon: BitmapDescriptor.fromBytes(destinationIcon), // icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed), ); _markers.add(destinationMarker); controller.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( target: LatLng(_eventLocation.latitude, _eventLocation.longitude), zoom: 16, ), ), ); setState(() {}); } } ```

Screenshots or Video

Screenshots / Video demonstration Left one is from Desktop browser and Right one is from Mobile browser Screenshot 2024-04-29 at 8 17 53 PM

Logs

Logs ```console [Paste your logs here] ```

Flutter Doctor output

Doctor output ```console Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.16.2, on macOS 14.3.1 23D60 darwin-arm64, locale en-IN) [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2023.2) [✓] Connected device (3 available) [✓] Network resources • No issues found! ```
darshankawar commented 2 weeks ago

Thanks for the report @kalpeshmayani

but not displays marker in mobile browser

Is this on android chrome or iOS safari ?

Also, can you provide us only minimal but complete reproducible without third party implementation which still shows the reported behavior ?

kalpeshmayani commented 2 weeks ago

Thanks for quick response.

So I am not sure about android mobile browser, but markers not displaying on iOS mobile browser(chrom + safari) for sure. There is no thrid party dependecy added other than google maps in given code. And that what I am having in my code.

darshankawar commented 2 weeks ago

@kalpeshmayani I was mentioning about below custom implementation you have in the code provided:

Screenshot 2024-05-02 at 11 51 25 AM

That's why we request to provide only minimal but complete runnable code that is enough to replicate the reported behavior and you may remove the unnecessary implementations.

kalpeshmayani commented 1 week ago

Ohh, sorry, I though about third party packages. And I updated my code here.

import 'dart:async';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class EventMapWidget extends StatefulWidget {
  EventMapWidget({
    Key? key,
  }) : super(key: key);

  @override
  _EventMapWidgetState createState() => _EventMapWidgetState();
}

class _EventMapWidgetState extends State<EventMapWidget> {
  final Completer<GoogleMapController> _controller = Completer();

  Set<Marker> _markers = {};
  Set<Circle> _circles = {};
  Map<PolylineId, Polyline> _polylines = {};

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.all(
        Radius.circular(5),
      ),
      child: AbsorbPointer(
        absorbing: true,
        child: Stack(
          children: <Widget>[
            Positioned(
              child: GoogleMap(
                initialCameraPosition:
                    const CameraPosition(target: LatLng(0.0, 0.0)),
                myLocationButtonEnabled: false,
                zoomGesturesEnabled: false,
                zoomControlsEnabled: false,
                rotateGesturesEnabled: false,
                scrollGesturesEnabled: false,
                tiltGesturesEnabled: false,
                circles: Set<Circle>.from(_circles),
                markers: Set<Marker>.from(_markers),
                polylines: Set<Polyline>.of(_polylines.values),
                gestureRecognizers: Set()
                  ..add(Factory<PanGestureRecognizer>(
                      () => PanGestureRecognizer()))
                  ..add(Factory<ScaleGestureRecognizer>(
                      () => ScaleGestureRecognizer()))
                  ..add(Factory<TapGestureRecognizer>(
                      () => TapGestureRecognizer()))
                  ..add(Factory<VerticalDragGestureRecognizer>(
                      () => VerticalDragGestureRecognizer()))
                  ..add(Factory<HorizontalDragGestureRecognizer>(
                      () => HorizontalDragGestureRecognizer()))
                  ..add(Factory<OneSequenceGestureRecognizer>(
                      () => EagerGestureRecognizer())),
                onMapCreated: (GoogleMapController controller) async {
                  _controller.complete(controller);
                  _showLocationOnMap(context);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  _showLocationOnMap(BuildContext context) async {
    final GoogleMapController controller = await _controller.future;

    // set marker for event address location
    Marker destinationMarker = Marker(
      markerId: MarkerId('unique_id'),
      position: LatLng(
        21.230200,
        72.862840,
      ),
      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
    );

    _markers.add(destinationMarker);

    controller.animateCamera(
      CameraUpdate.newCameraPosition(
        CameraPosition(
          target: LatLng(21.230200, 72.862840),
          zoom: 16,
        ),
      ),
    );

    setState(() {});
  }
}
darshankawar commented 1 week ago

Thanks for the updated code. Using it, I was able to replicate the reported behavior on mobile web (both, android + chrome and ios + safari).

stable, master flutter doctor -v ``` [!] Flutter (Channel stable, 3.19.6, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.19.6 on channel stable at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision 54e66469a9 (6 days ago), 2024-04-17 13:08:03 -0700 • Engine revision c4cd48e186 • Dart version 3.3.4 • DevTools version 2.31.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. [!] Flutter (Channel master, 3.22.0-22.0.pre.6, on macOS 12.2.1 21D62 darwin-x64, locale en-GB) • Flutter version 3.22.0-22.0.pre.6 on channel master at /Users/dhs/documents/fluttersdk/flutter ! Warning: `flutter` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter. Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision d34d4cd125 (16 minutes ago), 2024-05-02 03:08:30 -0400 • Engine revision fc28057dbd • Dart version 3.5.0 (build 3.5.0-122.0.dev) • DevTools version 2.35.0 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) • Android SDK at /Users/dhs/Library/Android/sdk ✗ cmdline-tools component is missing Run `path/to/sdkmanager --install "cmdline-tools;latest"` See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 13C100 • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] IntelliJ IDEA Ultimate Edition (version 2021.3.2) • IntelliJ at /Applications/IntelliJ IDEA.app • Flutter plugin version 65.1.4 • Dart plugin version 213.7228 [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.29.0 [✓] Connected device (3 available) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 15.3.1 19D52 • macOS (desktop) • macos • darwin-x64 • macOS 12.2.1 21D62 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. [!] Xcode - develop for iOS and macOS (Xcode 12.3) • Xcode at /Applications/Xcode.app/Contents/Developer ! Flutter recommends a minimum Xcode version of 13. Download the latest version or update via the Mac App Store. • CocoaPods version 1.11.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] VS Code (version 1.62.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (5 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 11 (API 30) • Darshan's iphone (mobile) • 21150b119064aecc249dfcfe05e259197461ce23 • ios • iOS 14.4.1 18D61 • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 [✓] HTTP Host Availability • All required HTTP hosts are available ! Doctor found issues in 1 category. ```
abigotado commented 1 week ago

I'm experiencing the same issue and have some additional details.

First, here's how I create custom markers from svg:

Future<BitmapDescriptor> getBitmapDescriptorFromSvgAsset(
    final BuildContext context,
    final String assetName, {
    final Size size = const Size.square(30),
    final ColorMapper? colorMapper,
  }) async {
    final ui.FlutterView view = View.of(context);
    final PictureInfo pictureInfo = await vg.loadPicture(
      SvgAssetLoader(assetName, colorMapper: colorMapper),
      context,
    );

    final double devicePixelRatio = view.devicePixelRatio;
    final int width = (size.width * devicePixelRatio).toInt();
    final int height = (size.height * devicePixelRatio).toInt();

    final double scaleFactor = min(
      width / pictureInfo.size.width,
      height / pictureInfo.size.height,
    );

    final ui.PictureRecorder recorder = ui.PictureRecorder();

    ui.Canvas(recorder)
      ..scale(scaleFactor)
      ..drawPicture(pictureInfo.picture);

    final ui.Picture rasterPicture = recorder.endRecording();

    final ui.Image image = rasterPicture.toImageSync(width, height);
    final ByteData bytes =
        (await image.toByteData(format: ui.ImageByteFormat.png))!;

    return BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
  }

In mobile browsers (Chrome/Safari) it is throwing

Uncaught Unsupported operation: toImageSync is not supported on the HTML backend. Use drawPicture instead, or toImage.

So I tried to replace final ui.Image image = rasterPicture.toImageSync(width, height); with final ui.Image image = await rasterPicture.toImage(width, height);

Well, it sometimes works (not always, can't find out in which cases it works, in which not). But it renders markers incorrectly: Instead of this Снимок экрана 2024-05-02 в 18 26 25 it renders this Снимок экрана 2024-05-02 в 18 30 41. As you can see - some white frame appears around the picture.

I think the problem is related to the HTML renderer, 'cause the problem disappears, if you use --web-renderer=canvaskit. But with canvaskit the marker becomes larger in mobile browser (in desktop Chrome everything is okay). Снимок экрана 2024-05-02 в 18 34 09

Flutter Doctor output

Doctor output ```console Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.19.6, on macOS 14.4.1 23E224 darwin-arm64, locale ru-RU) [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.3) [✓] Chrome - develop for the web [✓] Android Studio (version 2023.1) [✓] IntelliJ IDEA Ultimate Edition (version 2024.1) [✓] IntelliJ IDEA Community Edition (version 2022.2) [✓] VS Code (version 1.88.1) [✓] Connected device (4 available) ! Error: Browsing on the local area network for iPhoneK. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac. The device must be opted into Developer Mode to connect wirelessly. (code -27) [✓] Network resources ```