npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-maps-fleets

v0.2.0

Published

Fleet-oriented native clustering wrapper for react-native-maps

Downloads

133

Readme

react-native-maps-fleets

A production-ready fleet map wrapper around react-native-maps with native clustering and patch-based updates.

Install

yarn add react-native-maps-fleets react-native-maps
cd ios && pod install

Google Maps API key

Android (required): add a Google Maps API key to your AndroidManifest.xml:

<meta-data
  android:name="com.google.android.geo.API_KEY"
  android:value="YOUR_API_KEY" />

Expo config plugin (optional):

// app.json or app.config.js
{
  "expo": {
    "plugins": [
      [
        "react-native-maps-fleets/plugin/withFleetMaps",
        {
          "androidApiKey": "YOUR_API_KEY",
          "iosApiKey": "YOUR_IOS_KEY",
          "streetViewApiKey": "YOUR_STREET_VIEW_KEY"
        }
      ]
    ]
  }
}

iOS: add GMSApiKey to Info.plist for Google Maps on iOS.

Usage

import React from 'react';
import {FleetMapView, Cluster, NormalMarker, AdvancedMarker} from 'react-native-maps-fleets';

const features = [
  {
    id: 'truck-1',
    coordinate: {latitude: 37.78, longitude: -122.41},
    type: 'vehicle',
    clusterId: 'main',
    heading: 120,
    zIndex: 10,
  },
];

export default function FleetScreen() {
  return (
    <FleetMapView
      style={{flex: 1}}
      initialRegion={{
        latitude: 37.78,
        longitude: -122.41,
        latitudeDelta: 0.1,
        longitudeDelta: 0.1,
      }}
      features={features}
      selectedId={null}
      onSelect={id => console.log('select', id)}
      clusterIdDefault="main">
      <Cluster id="main">
        <NormalMarker type="vehicle" icon="car" rotatable zIndex={10} />
        <NormalMarker type="arrow" icon="arrow" rotatable zIndex={20} />
        <NormalMarker type="avatar" size={64} zIndex={30} />
      </Cluster>

      <Cluster id="secondary">
        <NormalMarker type="poi" icon="pin" zIndex={5} />
      </Cluster>

      <AdvancedMarker coordinate={{latitude: 37.78, longitude: -122.41}}>
        <SelectedVehicle />
      </AdvancedMarker>
    </FleetMapView>
  );
}

Performance Mode

Performance Mode is a set of optimizations for fleet-scale maps (200–1000+ moving devices), ensuring smooth movement and reduced CPU/GPU usage.

Why we never use iconView for mass markers

When rendering hundreds of markers, using iconView (UIView-based markers) leads to severe performance degradation and visual artifacts:

  • GPU Texture Pressure: Each iconView requires a snapshot that is stored as a GPU texture. 300+ live views can exceed GPU memory or cause texture thrashing.
  • Snapshot Corruption: Rapid movement or zoom changes during view snapshotting can cause "stretched" or falsified visuals (e.g., random red blocks).
  • Main Thread Blockage: React Native and the Map SDK must manage the lifecycle of hundreds of UIViews on the main thread.

Solution: In Performance Mode, we use pre-rendered marker.icon bitmaps. These are generated once, cached in an LRU cache, and reused across all markers with the same visual state.

Advanced Optimizations

  • Size Buckets: To maximize cache hits, marker sizes are quantized into a few "buckets" (e.g., small, medium, large).
  • Off-Main Processing: Image decoding, resizing, and marker composition (drawing borders, pins, etc.) happen on background threads. Only the final assignment to the marker happens on the main thread.
  • In-Flight Deduplication: If multiple markers request the same avatar URL simultaneously, only one download/process task is started.
  • Stable Z-Index: Marker layering is updated only when necessary (creation or selection change), eliminating per-tick overhead.
  • Out-of-Viewport Cadence: Markers outside the viewport remain visible but update their positions much less frequently (e.g., every 2.5s) to save CPU.

Features

  • Hot Path (Positions): Throttled and interpolated native updates.
  • Cold Path (Visuals): Efficient batch updates for selection and icon changes.
  • Authoritative Native Registry: Ensures 1 ID maps to exactly 1 native marker.
  • Viewport Virtualization: Skips processing for markers outside the camera view + buffer.
  • Zoom-driven Aggressive Clustering: Automatically hides/clusters markers at low zoom levels.
  • Cap Visible Singles: Limits the number of single markers in the viewport to prioritize performance.
  • Performance Cluster: Native clustering for high-density marker sets (200–1000+), automatically grouping background markers while keeping the selected marker as a distinct, single entity.

How to Enable

You can enable it via props or by calling the imperative method:

<FleetMapView
  performanceModeEnabled={true}
  performanceConfig={{
    performanceCluster: true,
    performanceClusterConfig: {
      clusterZoomThreshold: 12,
      clusterDensityThreshold: 250,
    },
    // ...
  }}
/>

Or imperatively:

mapRef.current.setPerformanceMode(true, { performanceCluster: true });

Performance Cluster Behavior

When performanceCluster is active:

  1. Zoom Threshold: Markers are clustered when the zoom level is below clusterZoomThreshold.
  2. Density Threshold: If the number of visible markers exceeds clusterDensityThreshold, clustering activates even if zoom is high.
  3. Selected Marker Exclusion: The currently selected marker is NEVER clustered. It remains a single, high-fidelity marker (arrow/avatar) regardless of zoom or density.
  4. Hysteresis & Throttling: Clustering updates are throttled (default 350ms) to avoid CPU spikes during movement).

Configuration Options

| Option | Default | Description | | --- | --- | --- | | performanceCluster | false | Enable/disable native performance clustering. | | clusterZoomThreshold | 12 | Zoom level below which background markers are clustered. | | clusterDensityThreshold | 250 | Number of markers above which clustering is forced. | | clusterUpdateThrottleMs | 350 | Throttling interval for native clustering logic. | | alwaysShowSelected | true | If true, selected marker is always excluded from clusters. |

Troubleshooting

  • Ghost Markers: Ensure you are using unique IDs. Performance mode enforces a strict 1-to-1 registry.
  • Arrows not moving: Ensure the marker type is set correctly and heading is provided in the position update.

Performance tips

  • Prefer features + patchPositions updates (patches are computed automatically in JS).
  • Use selectedId to promote one feature out of the clustered set.
  • Keep marker types stable and reuse marker icons.
  • Avoid re-creating the features array when not needed.

Native Architecture

Both platforms implement a full-featured FleetMarkerEngine with identical subsystems:

| Component | Purpose | |---|---| | FleetMarkerEngine | Main engine coordinating all subsystems | | MarkerStore | Thread-safe O(1) marker state storage | | MarkerPool | Object pooling for zero-alloc scrolling | | VisibilityIndex | 3-zone viewport culling with hysteresis | | ClusterGrid | O(N) spatial-hash clustering | | MarkerRegistry | 1-to-1 ID-to-native-marker mapping | | SelectionController | Selection state management | | UpdateScheduler | Budget-limited tick execution | | IconCache | LRU icon cache (Android: LruCache, iOS: NSCache) |

  • Android: Kotlin, Google Maps SDK, Handler-based animation
  • iOS: Swift, Google Maps SDK, CADisplayLink 60fps animation, GCD background processing

See API.md for the full API reference.

Limitations

  • Advanced markers are rendered in React; avoid heavy layouts.

Roadmap

  • Custom cluster styling hooks.
  • Optional map state persistence.

License

MIT. Includes copyright from Airbnb and Nicola Tomassini.