Repository navigation
Description
Steps to reproduce
AdvancedMarker with BitmapDescriptor.bytes flickers/disappears on web during position updates
When using google_maps_flutter_web with AdvancedMarker icons backed by BitmapDescriptor.bytes / BytesMapBitmap, the marker content disappears briefly whenever the marker position is updated repeatedly.
This only appears to happen on web. The same marker movement is smooth when the marker uses PinConfig with a TextGlyph.
Depending on how heavy the surrounding application is, the flicker appears worse / it takes longer to finally draw the marker.
Reproduction outline
- Create a web
GoogleMapusing advanced markers. - Add an
AdvancedMarkerwhose icon is created withBitmapDescriptor.bytes(...)orBytesMapBitmap(...). - Repeatedly update the marker with the same marker ID and same icon, but a new
position. - Observe that the marker content disappears/flickers during movement.
- Repeat with a
PinConfig(glyph: TextGlyph(...)). - Observe that the
PinConfig/TextGlyphmarker moves smoothly.
Investigation
The web implementation appears to rebuild and reassign AdvancedMarkerElement.content on every marker update, even when only the marker position changed.
For byte-backed bitmap markers, rebuilding the content creates a new image/blob-backed DOM node. Reassigning that content during every position update causes the marker to temporarily disappear while the image content loads/renders again.
PinConfig / TextGlyph does not show the same behavior because it creates synchronous DOM content rather than a byte-backed image that needs to reload.
Suggested fix
Only update AdvancedMarkerElement.content when the visual marker content actually changes, such as when the icon, alpha, visibility, or rotation changes. Position-only updates should update the marker position without replacing the existing DOM content.
Expected results
Updating an AdvancedMarker position should move the existing marker content smoothly, without the icon disappearing or flickering.
Actual results
When the marker uses byte-backed bitmap content, moving the marker causes the marker icon/text image to disappear from the map until the marker remains in the same position long enough for the content to render again. During frequent position updates, this creates a very flickery experience.
Code sample
Code sample
import 'dart:async';
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() {
runApp(const MaterialApp(home: AdvancedMarkerBytesFlickerRepro()));
}
class AdvancedMarkerBytesFlickerRepro extends StatefulWidget {
const AdvancedMarkerBytesFlickerRepro({super.key});
@override
State<AdvancedMarkerBytesFlickerRepro> createState() =>
_AdvancedMarkerBytesFlickerReproState();
}
class _AdvancedMarkerBytesFlickerReproState
extends State<AdvancedMarkerBytesFlickerRepro> {
static const LatLng _center = LatLng(-33.852, 151.211);
static const String _mapId = 'DEMO_MAP_ID';
BitmapDescriptor? _bytesIcon;
Timer? _timer;
int _tick = 0;
final BitmapDescriptor _pinIcon = BitmapDescriptor.pinConfig(
backgroundColor: Colors.blue,
borderColor: Colors.blue,
glyph: const TextGlyph(text: 'PIN', textColor: Colors.white),
);
@override
void initState() {
super.initState();
_createBytesIcon().then((BitmapDescriptor icon) {
if (!mounted) {
return;
}
setState(() {
_bytesIcon = icon;
});
_timer = Timer.periodic(const Duration(milliseconds: 80), (_) {
setState(() {
_tick++;
});
});
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
Set<AdvancedMarker> _markers() {
final BitmapDescriptor? bytesIcon = _bytesIcon;
if (bytesIcon == null) {
return <AdvancedMarker>{};
}
final double phase = _tick / 8.0;
final double latOffset = math.sin(phase) * 0.0015;
return <AdvancedMarker>{
AdvancedMarker(
markerId: const MarkerId('bytes-marker'),
position: LatLng(_center.latitude + latOffset, _center.longitude - 0.003),
icon: bytesIcon,
),
AdvancedMarker(
markerId: const MarkerId('pin-marker'),
position: LatLng(_center.latitude + latOffset, _center.longitude + 0.003),
icon: _pinIcon,
),
};
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
mapId: _mapId,
markerType: GoogleMapMarkerType.advancedMarker,
initialCameraPosition: const CameraPosition(target: _center, zoom: 16),
markers: _markers(),
),
);
}
Future<BitmapDescriptor> _createBytesIcon() async {
final Uint8List bytes = await _createPngBytes('BYTES');
return BitmapDescriptor.bytes(bytes, width: 96, height: 42);
}
Future<Uint8List> _createPngBytes(String text) async {
const double width = 192;
const double height = 84;
final ui.PictureRecorder recorder = ui.PictureRecorder();
final Canvas canvas = Canvas(recorder);
final Paint fill = Paint()..color = Colors.red;
canvas.drawRRect(
RRect.fromRectAndRadius(
const Rect.fromLTWH(0, 0, width, height),
const Radius.circular(18),
),
fill,
);
final TextPainter painter = TextPainter(
text: TextSpan(
text: text,
style: const TextStyle(
color: Colors.white,
fontSize: 34,
fontWeight: FontWeight.bold,
),
),
textDirection: TextDirection.ltr,
)..layout(maxWidth: width);
painter.paint(
canvas,
Offset((width - painter.width) / 2, (height - painter.height) / 2),
);
final ui.Image image = await recorder.endRecording().toImage(
width.toInt(),
height.toInt(),
);
final ByteData? byteData = await image.toByteData(
format: ui.ImageByteFormat.png,
);
return byteData!.buffer.asUint8List();
}
}Screenshots or Video
Screenshots / Video demonstration
Screen.Recording.2026-06-22.at.4.16.36.PM.mov
Screenshots / Video demonstration
Screen.Recording.2026-06-22.at.3.49.39.PM.mov
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.44.0, on macOS 26.4.1 25E253 darwin-arm64, locale en-NZ)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 26.5)
[✓] Chrome - develop for the web
[✓] Connected device (2 available)
! Error: Browsing on the local area network for Jack’s iPad. 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)
! Error: Browsing on the local area network for iPhone (2). 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)
! Error: Browsing on the local area network for iPhone. 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
• No issues found!
Activity
suryaKommana2662 commentedon Jun 22, 2026
@Gibbo97 Thanks for the detailed report, reproducible sample, investigation, video demonstrations, and the additional information regarding the proposed fix - #11952
This issue contains sufficient information to investigate and appears to affect the web implementation of
google_maps_flutterwhen updatingAdvancedMarkerinstances backed by byte-based bitmap content. Routing this issue to theteam-ecosystemfor further investigation.[google_maps_flutter_web] Avoid replacing advanced marker content on …
[google_maps_flutter_web] Avoid replacing advanced marker content on …
[google_maps_flutter_web] Avoid replacing advanced marker content on …
github-actions commentedon Sep 22, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.