Add advanced markers support - #48
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughAdds a ChangesAdvanced marker support
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@demo/advanced-markers-clustering.html`:
- Around line 42-60: Move the marker-generation loop into a one-time dom-change
listener on the surrounding template so it runs only after dom-bind stamps `#map`.
Resolve `#map` inside that callback before appending the generated markers,
preserving the existing deterministic positions and marker properties.
In `@google-map-advanced-marker.js`:
- Around line 429-436: Update the click handling around openInfoHandler_ and the
corresponding clickEvents listener so long-press suppression is evaluated by one
shared dispatcher before either listener acts. Ensure _suppressNextClick is
cleared only after all handlers for that click have been prevented from
forwarding, so enabling both InfoWindow and clickEvents still swallows the
synthetic click.
- Around line 296-309: Update the detached()/attached() lifecycle so detaching
does not leave the marker with missing subscriptions or unreleasable Maps
listener handles. Either preserve _listeners and DOM/content subscriptions
during detachment, or have attached() fully recreate them—including
mouse/double-click forwarding, content observation, and listener
bookkeeping—before restoring the marker with setMap(this.map).
- Around line 390-402: Update _mapChanged() and _mapReady() to use a
map/generation token for each marker-construction attempt. Capture the current
token before asynchronous marker loading, and have _mapReady() abort when the
token no longer matches the latest map change; ensure only the still-current
attempt constructs and attaches a marker.
- Around line 378-381: Update _collisionBehaviorChanged() so it always
synchronizes the marker when collisionBehavior changes: assign the mapped
CollisionBehavior value when configured, and reset the marker’s
collisionBehavior when the property is null or cleared instead of leaving the
previous value active.
- Around line 443-449: Update the this.info cleanup branch to close the existing
InfoWindow before removing its listeners and setting this.info to null. Preserve
the current listener removal, clickable-state update, and empty-window cleanup
behavior.
In `@README.md`:
- Line 15: Update the README import and usage examples to include the
advanced-marker component alongside the legacy marker example, and configure the
map with the required map-id attribute. Keep the existing legacy example intact
while making the advertised AdvancedMarkerElement feature directly actionable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d3901360-d620-40c4-9016-43621c0e5283
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mddemo/advanced-markers-clustering.htmldemo/advanced-markers.htmlgoogle-map-advanced-marker.jsgoogle-map-elements.jsgoogle-map-marker.jsgoogle-map.jspackage.json
6a94172 to
0944064
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@google-map-advanced-marker.js`:
- Around line 296-303: Update detached() and the marker replacement cleanup
around _touchTimer to cancel any pending long-press timer when the marker is
removed or replaced, clear its reference, and preserve the existing listener and
observer cleanup behavior.
- Around line 537-541: Update the initialization flow around _openChanged() so
it does not close an InfoWindow or emit google-map-marker-close when open is
initially false and the window was never opened. Only invoke the open-state
change handling when the component has an established/open state that requires
synchronization, while preserving the existing content, click, drag, and mouse
event setup.
- Around line 513-523: Update the AdvancedMarkerElement construction to parse
latitude and longitude first, and include the position option only when both
parsed values are finite. When either coordinate is null, invalid, or
non-finite, omit position entirely while preserving the other marker options.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: aba9bd52-4c41-4f4a-82ec-4347a35f0771
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mddemo/advanced-markers-clustering.htmldemo/advanced-markers.htmlgoogle-map-advanced-marker.jsgoogle-map-elements.jsgoogle-map-marker.jsgoogle-map.jspackage.json
0944064 to
edd7428
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
✅ Action performedFull review finished. Your plan includes PR reviews subject to rate limits. More reviews will be available in 57 minutes. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@google-map-advanced-marker.js`:
- Around line 721-774: Update _setupTouchAndHold’s pointerdown handler to start
the long-press timer only for primary touch or other touch-like pointers,
ignoring mouse and non-primary pointer events. Add pointercancel to the
clearTimer cancellation listeners so cancelled gestures always stop the timer.
- Around line 315-321: Update _updatePosition() to parse latitude and longitude
once, validate that both coordinates are finite, and assign marker.position to
the coordinate object only when valid; otherwise assign null so missing or
invalid values clear any existing pin.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 59d0bec6-7c82-4d3d-9621-512dab5b9443
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mddemo/advanced-markers-clustering.htmldemo/advanced-markers.htmlgoogle-map-advanced-marker.jsgoogle-map-elements.jsgoogle-map-marker.jsgoogle-map.jspackage.json
edd7428 to
e46cf64
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@google-map-advanced-marker.js`:
- Around line 324-337: Update _clickEventsChanged() to cancel any pending
touch-and-hold timer when clickEvents becomes false, before or alongside
clearing the DOM listeners. Reuse the existing touch-hold cleanup state or
method used by _setupTouchAndHold(), ensuring no delayed rightclick event is
emitted after click events are disabled.
- Around line 451-461: Update the InfoWindow creation flow in the
content-handling method so that when dynamic content creates this.info while
open is already true, it immediately opens the InfoWindow using the marker’s
existing open behavior. Preserve the current click-handler setup and avoid
changing behavior when open is false.
- Around line 694-697: Update getPosition() to validate parsed latitude and
longitude before constructing a LatLng, returning null when either coordinate is
missing or non-finite. In _loadMarkersCluster(), filter this.markers so only
markers with valid positions are passed to MarkerClusterer, ensuring
Supercluster never receives unpositioned markers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6aa6f13e-5308-41f7-8761-07b37de28f0f
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mddemo/advanced-markers-clustering.htmldemo/advanced-markers.htmlgoogle-map-advanced-marker.jsgoogle-map-elements.jsgoogle-map-marker.jsgoogle-map.jspackage.json
e46cf64 to
0af5917
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
demo/advanced-markers-clustering.html (1)
55-69: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winBatch marker appends using a
DocumentFragment.Appending markers to the
mapelement individually inside the loop can trigger multiple synchronous layouts and unnecessarily fire the<google-map>'s internal mutation observer 60 times.Using a
DocumentFragmentwill batch the insertions, allowing the map component to process all added markers in a single observer execution.⚡ Proposed optimization
+ const fragment = document.createDocumentFragment(); for (let i = 0; i < 60; i++) { const marker = document.createElement('google-map-advanced-marker'); marker.setAttribute('slot', 'markers'); marker.latitude = CENTER.lat + (random() - 0.5) * 0.5; marker.longitude = CENTER.lng + (random() - 0.5) * 0.5; marker.title = 'Marker ' + (i + 1); marker.background = COLORS[i % COLORS.length]; marker.glyphColor = '`#FFFFFF`'; marker.glyph = String(i + 1); marker.clickEvents = true; marker.addEventListener('google-map-marker-click', function(e) { console.log(this.title + ' clicked', e.detail.latLng.lat(), e.detail.latLng.lng()); }); - map.appendChild(marker); + fragment.appendChild(marker); } + map.appendChild(fragment);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@demo/advanced-markers-clustering.html` around lines 55 - 69, Update the marker creation loop in the clustering demo to append each new marker to a DocumentFragment instead of directly to map, then append the populated fragment to map once after the loop. Preserve all marker configuration and click handling unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@google-map-advanced-marker.js`:
- Around line 557-565: Prevent the initial setup path from calling _openChanged
when open is already true, since _contentChanged has already created and opened
the InfoWindow and dispatched the event. Preserve _openChanged for later
open-state changes so each transition still emits exactly once.
- Around line 559-567: Move the setupDragHandler_().bind(this)() call before
_dragEventsChanged() during initialization. Preserve the existing mouse-event
handling and conditional _openChanged() behavior, ensuring the drag handler is
registered before the first dragend event can be forwarded so latitude and
longitude are updated first.
In `@google-map.js`:
- Around line 966-968: Update the customRenderer handling to remove eval()
entirely and accept only a renderer object supplied through property binding. In
the relevant renderer-options logic, assign customRenderer directly when it is
an appropriate object, while rejecting or ignoring string values so no
user-provided JavaScript is executed.
---
Nitpick comments:
In `@demo/advanced-markers-clustering.html`:
- Around line 55-69: Update the marker creation loop in the clustering demo to
append each new marker to a DocumentFragment instead of directly to map, then
append the populated fragment to map once after the loop. Preserve all marker
configuration and click handling unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d8db2012-10a9-4c51-b96b-56003f9a41a1
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
README.mddemo/advanced-markers-clustering.htmldemo/advanced-markers.htmlgoogle-map-advanced-marker.jsgoogle-map-elements.jsgoogle-map-marker.jsgoogle-map.jspackage.json
0af5917 to
2063fa1
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
Code Review FindingsThe following review was generated by Claude. 🔴 1. Markers positioned after insertion are permanently dropped from clusters —
|
|
Thanks for the review — all three are addressed (pushed as WIP commits): 1. Markers positioned after insertion dropped from clusters — b11e5c5. The map now listens for a 2. Stale 3. Cached |
All fixed, see #48 (comment) |
Code Review FindingsThe following review was generated by Claude. 🔴 1. Unhandled promise rejection if the marker library fails to load —
|
|
Thanks — addressed as separate WIP commits: 1. Unhandled rejection on marker-library load failure — fd43213. 2. 3. Stale 4. Divergent removal predicates — fac2843. 6. Full clusterer rebuild per position change — c28bc7b. The clusterer has no incremental-update API (reassigning 5. Classic marker doesn't dispatch the event — this asymmetry is intentional. Classic markers always return a |
javier-godoy
left a comment
There was a problem hiding this comment.
Note
This review was produced by Claude (Claude Code), reviewed and endorsed by me before posting.
Nice work on the advanced markers element — the new google-map-marker-position-changed path is the right idea. Most of the comments below cluster on that path, where I think the implementation doesn't yet deliver what the doc comment promises.
Blocking, in rough priority order:
- The cluster refresh can't actually re-cluster a marker that moves (
google-map.js:997) —MarkerClusterer's algorithm short-circuits on an identity-equal marker array, so the stale coordinates survive. - The event is never dispatched for coordinates set before the async marker build finishes (
google-map-advanced-marker.js:318). fit-to-markersnow hijacks the viewport on every drag (google-map.js:1001) — a behavior regression relative togoogle-map-marker.
The remaining comments are on the new element itself (InfoWindow re-anchoring, the slot-resolution mismatch, stopPropagation on forwarded DOM events, the unguarded e.latLng, and the marker.map collision with the clusterer). The last three are mechanism-verified from the code but I have not reproduced them in a browser — please confirm before changing anything there.
Duplication between google-map-marker and google-map-advanced-marker is not a concern for me — the classic element is slated for removal, so I'm treating that as transitional by design. Likewise, I'm not asking you to backport the new position-changed event to google-map-marker.
| } | ||
| this.debounce('markerPositionChanged', () => { | ||
| if (this.enableMarkersClustering && this.markerCluster) { | ||
| this.markerCluster.markers = this._getClusterableMarkers(); |
There was a problem hiding this comment.
This refresh can't re-cluster a marker that moves between two valid positions.
_getClusterableMarkers() returns a new array holding the same element references. In @googlemaps/markerclusterer 2.6.2 (the version pinned here), SuperClusterAlgorithm.calculate does a deepEqual on the marker array, not on the positions — so when membership is unchanged it short-circuits and never calls superCluster.load(points). The spatial index keeps the old coordinates.
Repro: with enable-markers-clustering, drag an advanced marker across the map (or set latitude/longitude from one valid value to another). The pin moves, but its cluster bubble and count stay at the original location, and zooming doesn't fix it because zoom changes only re-query the stale index.
So the handler works for markers that gain or lose a position (membership changes) but not for markers that move — which is the case the doc comment above implies is covered. Forcing the algorithm to see a change (e.g. removeMarkers/addMarkers, or resetting markerCluster.algorithm) would be needed here.
| this.markerCluster.render(); | ||
| } | ||
| if (this.fitToMarkers) { | ||
| this._fitToMarkersChanged(); |
There was a problem hiding this comment.
Routing every coordinate change into _fitToMarkersChanged() makes fit-to-markers re-fit the viewport on marker drags, which it never did before — previously it ran only on marker add/remove and on the fitToMarkers property change.
With <google-map fit-to-markers> and <google-map-advanced-marker draggable>: the user drops a marker, onDragEnd_ writes the coordinates, the event fires, and 150 ms later the map calls fitBounds() + setCenter(). The map visibly jumps out from under the user after every drag, and google-map's own latitude/longitude/zoom get overwritten.
Worth distinguishing "a marker gained/lost a valid position" (should re-fit) from "a positioned marker moved" (probably shouldn't, at least not on a user drag).
There was a problem hiding this comment.
Context I should have included: I'm the one who asked for this call, in my 07-24 review (item 2, "fit-to-markers never re-fits after an async position update"), and you implemented it in 1a01c02. So this is not a request to revert it.
The distinction I failed to make: what I was after was the case where a marker's position first becomes valid — inserted without coordinates, _fitToMarkersChanged already ran and found zero positioned markers, then the coordinates arrive. The implementation covers that, but it also covers a positioned marker moving to a new position, which is where the drag regression comes from.
So the ask is to narrow it, not remove it: re-fit when a marker enters or leaves the set of positioned markers, skip it when an already-positioned marker just moves. Tracking whether the marker had a valid position before the change would be enough to tell those apart. Sorry for the extra round-trip.
| }, | ||
|
|
||
| _updatePosition() { | ||
| if (this.marker) { |
There was a problem hiding this comment.
The if (this.marker) guard means coordinates assigned before the marker finishes building are never reported to the parent map, and _mapReady doesn't dispatch the event after constructing the marker either — so that notification is lost entirely.
The window is real, not theoretical: _mapReady awaits google.maps.importLibrary('marker'), a network round-trip on first use. Concretely, with <google-map fit-to-markers> and a marker inserted without coordinates (the newly supported case):
_updateMarkers→_fitToMarkersChangedreturns early,positionedMarkers === 0._mapChanged→_mapReadysuspends on theimportLibraryawait.- The app sets
latitude/longitude.this.markeris stillundefined, so_updatePositionreturns without dispatching. _mapReadyresumes and builds the marker with the now-valid position — silently.
Result: the map is never centered on the marker (default world view, pin off-screen), and with enable-markers-clustering the marker renders un-clustered until some unrelated marker is added or removed. Dispatching the event at the end of _mapReady when a valid position exists would close it.
| } | ||
|
|
||
| function onDragEnd_(e, details, sender) { | ||
| this.latitude = e.latLng.lat(); |
There was a problem hiding this comment.
This dereferences e.latLng unguarded. It was copied verbatim from the classic marker, but _normalizeEvent further down in this same file exists precisely because AdvancedMarkerElement maps-events may not carry latLng for drag/dragstart/dragend — so the two pieces of code disagree about the same assumption.
If the payload lacks latLng, this throws Cannot read properties of undefined (reading 'lat') inside the Maps event dispatcher. Because setupDragHandler_ is registered before the forwarding listener, latitude/longitude are never updated and google-map-marker-dragend never fires — the dropped marker silently reverts to its old coordinates on the next re-render and the app never learns the new position.
I have not reproduced this in a browser, so please confirm whether dragend on an advanced marker does carry latLng in practice. Either way, routing this through _normalizeEvent (or guarding it the same way) would remove the inconsistency.
| const content = this._getInfoWindowContent(); | ||
| if (content) { | ||
| // honor an already-true open property when content first creates the InfoWindow | ||
| const shouldOpen = !this.info && this.open; |
There was a problem hiding this comment.
!this.info && this.open means _openChanged() runs only when the InfoWindow is created for the first time, so an open InfoWindow is never re-anchored after the marker is rebuilt. The classic google-map-marker calls this._openChanged() unconditionally at the end of _mapReady.
With open true, move the marker to another <google-map> (or otherwise reassign map): _mapChanged sets marker.map = null, which makes the Maps API close the anchored InfoWindow, then builds a new AdvancedMarkerElement. _contentChanged sees this.info already non-null, so shouldOpen is false and _openChanged() is skipped.
The popup disappears, and since this.open is still true, setting open = true again is a no-op — the caller has to toggle it to false first to get it back.
There was a problem hiding this comment.
Important constraint I left out: I now see both halves of what I flagged here are deliberate, and my pointer to the classic marker's unconditional _openChanged() is the wrong direction.
const shouldOpen = !this.info && this.open;came from CodeRabbit's "Honoropen=truewhen InfoWindow content is added later" — that's its proposed diff verbatim.- The unconditional
_openChanged()at the end of_mapReadywas removed on purpose per CodeRabbit's "Avoid dispatching the initial open event twice", and line 588 records it:// an initially-open InfoWindow is handled by _contentChanged (shouldOpen).
So please don't restore the unconditional call — that would reintroduce the duplicate google-map-marker-open emission on init.
The gap I'm actually reporting is narrower and I don't think it's covered by either thread: after the marker is rebuilt (_mapChanged → marker.map = null, which closes the anchored InfoWindow, then a fresh AdvancedMarkerElement), this.info is already non-null, so shouldOpen is false and nothing re-anchors the still-open window. A re-anchor on rebuild — conditional on the InfoWindow having been open before the rebuild, so init still emits exactly once — would cover it without touching the initial-open path.
| _getInfoWindowContent() { | ||
| const container = document.createElement('div'); | ||
| Array.prototype.forEach.call(this.childNodes, (node) => { | ||
| if (node.nodeType === Node.ELEMENT_NODE && node.getAttribute('slot') === 'content') { |
There was a problem hiding this comment.
This resolves the custom-content element differently from _buildContent, which uses this.querySelector('[slot="content"]') — a descendant match. Here the check only looks at direct children, so nested custom content isn't excluded from the InfoWindow markup.
With <google-map-advanced-marker><div><span slot="content">my pin</span></div></google-map-advanced-marker>: _buildContent adopts the <span> as the marker content, but this loop sees only the wrapper <div> (no slot attribute) and clones it whole — producing a spurious InfoWindow that duplicates the pin markup. Worse, once the marker adopts the span the wrapper is left empty, but container.innerHTML.trim() is still the non-empty string <div></div>, so an empty InfoWindow persists and pops up on every click on a marker that was meant to have none.
Using the already-resolved this._customContent for the exclusion would keep both sides in agreement.
| return; | ||
| } | ||
| } | ||
| e.stopPropagation(); |
There was a problem hiding this comment.
This stopPropagation() is unconditional, and it applies to the forwarded native DOM events (mousedown/mousemove/mouseup/mouseout/mouseover/dblclick) on a listener installed directly on the gmp-advanced-marker element. The Maps API's own gesture handlers live on ancestor nodes (map container, document/window), so stopping propagation here hides those events from them.
Expected effect with <google-map-advanced-marker mouse-events draggable="true">: the user can't pan the map by starting the drag on a marker, and marker dragging stalls whenever the cursor is over the marker element, since the API's drag tracker never sees mousedown/mousemove/mouseup. The classic marker forwarded google.maps events and never called stopPropagation, so mouse-events had no such side effect there.
Flagging this as needing a browser check rather than as a certainty. If suppression is only wanted for contextmenu/long-press, scoping it to those cases would be safer than applying it to all forwarded events.
| // Cannot use *Changed watchers for native properties. | ||
| switch (attrName) { | ||
| case 'hidden': | ||
| this.marker.map = this.hidden ? null : this.map; |
There was a problem hiding this comment.
Implementing visibility by writing this.marker.map uses the same channel MarkerClusterer uses to hide markers it has folded into a cluster — so this assignment can override the clusterer's decision. The classic marker used setVisible(), which doesn't collide.
With enable-markers-clustering, take a marker the clusterer has hidden (marker.map === null) and either toggle hidden true→false, or re-parent/move the element in the DOM (common under Vaadin), which runs attached() → setMap(this.hidden ? null : this.map). Either path sets marker.map = this.map, drawing the individual pin on top of the cluster bubble that still counts it — the same marker appears twice until the next full re-cluster.
Also unverified in a browser. If it reproduces, tracking the intended visibility separately from the clusterer's map assignment would be the fix.
Adds a new
google-map-advanced-markerelement based onAdvancedMarkerElement, Google's replacement for the deprecatedgoogle.maps.Marker. Part of FlowingCode/GoogleMapsAddon#121.The element supports pin customization (background, border color, glyph, scale). The original
google-map-markeris kept: advanced markers require amapIdand don't support some classic features (Symbolicons, labels, animation), so replacing it would break existing users. Per Google's deprecations page,google.maps.Markeris "not scheduled to be discontinued" and keeps working. A doc note now points new development to the new element.Added new demos:
demo/advanced-markers.htmlanddemo/advanced-markers-clustering.html.Summary by CodeRabbit
google-map-advanced-marker(based onAdvancedMarkerElement) with support for styled/icon/image markers, custom HTML content, dragging, InfoWindow open/close, and configurable event forwarding (including touch long-press “right-click”).fit-to-markersto use only valid coordinates with correct single-marker centering.map-id) and a usage example.