The third beta of Leaflet 2.0 makes chained view changes like setView(c).setZoom(z) or panTo(c).panBy(o) end where you'd expect, makes adding and removing event listeners up to hundreds of times faster on busy maps, and validates coordinates so bad data fails where it's created instead of somewhere deep in rendering. It also brings a round of keyboard and screen reader fixes for markers, popups and controls, along with over 15 bug fixes.
⚡️ Performance
- Make adding and removing event listeners constant-time: adding 50,000 markers with popups to a map takes 0.5 s instead of 15.6 s, and
on,off,onceandfireare faster in the common small cases too (#10537, #6914, #6923) - Position tooltips without measuring them, so maps with many permanent tooltips zoom without a forced layout per tooltip (#6948)
- Construct
Pointobjects ~40% faster, and the array and object forms ofPointandLatLng5–15% faster (#10550)
✨ Improvements
- Make view changes compose regardless of call order and timing:
setView(c)thensetZoom(z)(or the reverse) keeps both,panTo(c).panBy(o)ends atc + o, andzoomIn()calls during a zoom animation add up (#10549, #2609, #2915, #7766 by @Falke-Design) - Validate
PointandLatLngcoordinates, accepting numbers and numeric strings, and makePoint.validate()andLatLng.validate()match exactly what the constructors accept, so they can filter data (#10550, #7765 and #7767 by @johnd0e, #8214 by @Falke-Design) - Allow dragging the map during a zoom animation instead of treating the drag as a click (#8201)
- Let shift-drag pan the map and drag markers when box zoom is disabled (#2772, #6233, #7088)
- Honor
coords.zinTileLayer#getTileUrl, so it can build URLs for zoom levels other than the current one (#8849, #9201 by @yohanboniface) - Style
<button>and otherrole="button"elements inleaflet-barcontrols like links (#9462, @someonewithpc) - Support numeric strings and a partly automatic size like
[100, 'auto']iniconSize(#9253) - Add a
getEvents()hook to controls, like the one on layers: the map listeners it returns are added and removed with the control (#10229)
♿️ Accessibility
- Bring a focused marker to the front whatever
riseOnHoveris set to, so it's never hidden under its neighbors (#10536, #8078) - Return focus to the marker whenever its popup closes with focus inside it, not only on Escape (#10536, #8115)
- Set
aria-expandedandaria-controlson keyboard-accessible markers with a popup (#10536, #7527) - Move focus into a popup opened from a marker with the keyboard, and keep focus on a marker activated by a screen reader (#8113, #8114)
- Keep focus on a control after clicking it instead of moving it to the map (#7947)
- Make Space activate the zoom, layers and fullscreen buttons and the popup close button (#7369)
- Open tooltips only on keyboard focus, so a tooltip no longer appears when the window regains focus or a popup closes (#9150)
- Translate the default marker
alttext with thetranslatemap option (#10542 by @nfreear, #10541) - Raise the attribution and scale contrast to pass WCAG AA, with solid backgrounds and underlined links under
prefers-contrast: more(#6742, #7538, #10536)
🐞 Bug fixes
- Fix tiles flickering during fractional zoom animations past a layer's
maxZoom(#8300, #8311 by @sbquinlan) - Fix polygons disappearing when
weightis a string (#6072, #7432) - Fix tooltip positions in right-to-left containers (#7201, #7782)
- Fix the expanded layers list sometimes being covered by other controls (#7944)
- Fix a dragged marker's
autoPanpanning pastmaxBounds(#10539 by @A350xt, #6219) - Fix
DocumentFragmentpopup and tooltip content being empty after the first open (#10540 by @A350xt, #3922) - Fix
setIconkeeping the size, anchor,bgPosandcrossOriginof the previous icon when the new one doesn't set them (#10538 by @b84330808) - Fix
fitBoundsandgetBoundsZoomzooming all the way in when the padding is larger than the map (#10544 by @jayhemnani9910) - Fix
overlaps()onBoundsandLatLngBoundsreturningtruefor a point or line inside the other bounds (#10547 by @xunguangzlj-cloud) - Fix a layer with a
NaNminZoomormaxZoombreaking the map's zoom limits (#10548 by @xunguangzlj-cloud, #8354) - Fix
togglePopup()andtoggleTooltip()throwing on a layer that isn't on the map (#10551 by @Enesuygurs) - Fix listeners added during
firebeing called by that samefire, a regression from 1.x (#10537) - Fix
setViewwithworldCopyJumpleaving the map outside the main world copy when it doesn't animate (#10549) - Fix
getCenter()returning a center snapped to whole pixels right after the map is created
📝 Docs
- Mark the text that the
translateoption translates with a "Translatable" badge in the reference (#10546 by @Falke-Design) - Document the
flyToandpinchflags ofmoveandzoomevents (#9775), and how to stop control events from reaching the map (#10299)
⚠️ Breaking changes
LatLngandPointthrowInvalid LatLng object/Invalid Point objectfor coordinates that aren't numbers or numeric strings.null,''and booleans used to become0or1, and missing coordinates ({lat: 50}) gaveNaN. A non-numeric altitude throws too, andnullaltitude means no altitude instead of0.Pointconverts numeric strings to numbers instead of keeping them (#10550)- A non-numeric
radiuson a circle or circle marker throws, and a numeric string is converted to a number zoomIn(),zoomOut(),setZoom(),panTo()andpanBy()build on the view a running animation is heading to: two quickzoomIn()calls (or clicks on the zoom button) zoom in two levels.panByduring a zoom animation waits for it to end (#10549)riseOnHoveronly controls hover: focused markers always come to the front (#10536)- The attribution and scale controls have black text on a 90% white background, and attribution links are a darker blue (#6742, #7538)
Control#_refocusOnMapis gone.ZoomControl,ScaleControlandAttributionControladd their map listeners throughgetEvents(), andZoomControlandScaleControlno longer have anonRemovemethodTileLayer#_getZoomForUrltakes the tile zoom as an argument