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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@proofreason/ts-react-optimized-google-map

v0.1.7

Published

Typescript google maps wrapper optimized for react applications

Downloads

5

Readme

Typescript React optimized google maps

About

This is a typescript native, react google maps wrapper library aimed at performance, while maintaining react principles.

Disclaimer

This library is evolving very slowly now and is aimed at resolving issues I/we are having right now, so it is in no way a finnished product and is possibly subject to changes to the API and the way it works as a library. It is being used for stacionary marker display in production environments but we cannot guarantee reliability.

Use at your own risk.

Documentation

TODO: Will be present soon, although most can be deduced from types.

Get map with markers in 3 steps

I highly encourage you to look into a basic JS google maps api before using any library so you can understand its concepts better. We will not be documenting google maps api in this project.

We will asume you have your API setup in google console. You can use Basic Examples section to setup components we are mentioning

  1. First you need to mount google script so your global google object gets loaded. This can be done with our GoogleScriptMounter component.
  2. Second you need your google map which you need to mount somewhere. This can be done by mounting our GoogleMapsMounter. This will load the map into the mapElement.
  3. Then you want to add something to your map. We will add a marker using our Marker component.

From develop/examples/SimpleExample

    import { GoogleScriptMounter, GoogleMapsMounter, Marker } from '@proofreason/ts-react-optimized-google-map';

    const [isScriptLoaded, setScriptLoaded] = useState(false);
    const setScriptIsLoaded = () => setScriptLoaded(true);

    const mapWrapper = <div id={'map-mounter'} style={{ width: '800px', height: '500px' }} />;
    <GoogleScriptMounter scriptUrl={GOOGLE_API_URL} onScriptLoad={setScriptIsLoaded}>
            {isScriptLoaded && (
                <GoogleMapsMounter
                    mapElement={mapWrapper}
                    center={{ lat: NARNIA_REPUBLIC_LAT, lng: NARNIA_REPUBLIC_LONG }}
                    withMounter={true}
                >
                    <Marker
                        key={1}
                        id={1}
                        markerOptions={{
                            // google maps marker options
                            position: testPosition,
                            optimized: true,
                        }}
                    />
                </GoogleMapsMounter>
            )}
        </GoogleScriptMounter>

And that is it, you should see your marker at the given position.

There is one catch which is withMounter={true}. When this option is true, the GoogleMapsMounter will automatically include default MarkerMounter as its child so Marker components can mount. If you want MarkerMounter with custom option you just need to add one above your Marker components. But it must be under GoogleMapsMounter so it can get its context for the map.

Basic Examples

You can find example files at develop/examples/SimpleExample and develop/examples/Example

Google script Mounter

    <GoogleScriptMounter scriptUrl={GOOGLE_API_URL} onScriptLoad={setScriptIsLoaded}>
        ...
    </GoogleScriptMounter>

Google Maps Mounter with Map Controll

    const mapWrapper = <div id={'map-mounter'} style={{ width: '800px', height: '500px' }} />;
    <GoogleMapsMounter
        mapElement={mapWrapper}
        center={{ lat: NARNIA_REPUBLIC_LAT, lng: NARNIA_REPUBLIC_LONG }}
        withMounter={true}
    >
        <MapControll
            position={google.maps.ControlPosition.TOP_CENTER}
            offsets={{ topOffset: 30 }}
            containerStyle={{ width: '100%', pointerEvents: 'none' }}
        >
            <div>My custom controll</div>
        </MapControll>
        ...
    </GoogleMapsMounter>

Marker clusterer

    <MarkerClusterer
        onMountedMarkersUpdateStart={onUpdate}
        onMountedMarkersUpdateFinish={onUpdateFinish}
        clusteringSettings={{
            // extended markerclustererplus options
            onClickExtender: extendOurZoomOnClick,
            ignoreHidden: true,
            gridSize: 90,
            maxZoom: 5,
            averageCenter: true,
            zoomOnClick: false,
            calculator: calculateNumberInTheMiddleOfMarker,
        }}
    >
        ...
    </MarkerClusterer>

Marker mounter

    <MarkerMounter
        onMountedMarkersUpdateStart={onUpdate}
        onMountedMarkersUpdateFinish={onUpdateFinish}
        displayOnlyInFov={false}
    >
        ...
    </MarkerMounter>

Marker with Info Box

    <Marker
        key={id}
        id={id}
        onMouseEnter={mouseIsOverMarker}
        onMouseOut={mouseIsNotOverMarker}
        onClick={onMarkerMouseClick}
        markerOptions={{
            // google maps marker options
            position,
            optimized: true,
            icon,
            label,
            city: address.city,
        }}
        optimizations={{ listenersChanged: false //Can assume no listeners changed }}
    >
        <InfoBox
            position={new google.maps.LatLng(position.lat(), position.lng())}
            open={isOpen}
            {...{
                closeBoxURL: ``,
                enableEventPropagation: true,
                disableAutoPan: true,
                pixelOffset: new google.maps.Size(widthOffset, heightOffset),
                alignBottom: true,
                boxStyle: {
                    padding: '10px',
                    overflow: 'hidden',
                    width: '250px',
                    marginLeft: '-125px',
                    textAlign: 'center',
                },
            }}
        >
            <div>
                <div>{text}</div>
                <div>{subText}</div>
            </div>
        </InfoBox>
    </Marker>

Contribution

We are not quite yet ready for contributions of code from outside and don't have the resources to manage contributions. But if you find something you would like to implement or improve feel free to start a PR.

Also feel free to report any issues.

Implemented functionality

Optimized

  • Stacionary markers - Marker id is required for optimized updates
    • Marker loading
    • Marker updating
    • Marker rendering
  • Movable markers? - never tested thogh possibly functional

Basic implementation

  • Safe google script loading
  • Marker clustering
  • Info Box
  • Info Window
  • Map controll

To be done in near future (optimized or basic)

  • Marker spiderify - basic implementation might be present soon
  • Polygons - polygon drawing will be implemented in near future (level of optimization will be yet determined)
  • Marker Batching and Component Deconstruction - Experimental feature ready, to be improved soon.
    • Makrer components will be deconstructed to pure JS google objects and updates will be handled with a single component over a batch of JS objects removing the React overhead.

The problem

Bad perormance of js google map, when used with react.

  • performance is probably bad because the need to check many components for updates when working with large number of markers or other components.

This library aims at minimizing the amount of render and update cycles for markers while trying to maintain the "react way".

How it all works in the code (if you need to go to the code)

Unoptimized components

  • Most component use context to mount themselves to a map. So they don't need to be direct chilren of the mounter components, but they need a component that allows them to mount in their context (above in the tree).

  • Example of context distributing component is GoogleMapsMounter, which distributes the reference to the mounted map via its context.

Optimized components

  • Components like MarkerMounter or MarkerClusterer distribute their own context aswell Marker components use these contexts to register themselves at these contexts and the given mounter then takes care of mounting and unmounting the components.

  • Markers are updating through direct reference to their mounted js object in the Marker component.

Every optimized object like Marker must have ID provided to ensure it is the same marker and speed up the update.

Where is project used

This library is used in few comercial projects, but we cannot lost them here. Maybe we will add some examples in the future.