stepwise-map
v0.0.1
Published
### Map
Downloads
11
Readme
Key components
Map
This component represents map feature and is responsible for creating map using Google Maps Javascript API
It takes following props:
- google or window.google - it's main library object added under
window
to be a namespace for all useful features of Google Maps API. - options - configuration object for the map which reflects google.maps.MapOptions.
- bounds - collection of LatLng literals which represent area of interests and to which map will be adjusted. Map updates the bounds only when the reference to collection is changed.
- zoom - represents the map zoom which is adjusted when the property changes.
- onMapZoomChanged - callback which will be fired when the map zoom changes. It's worth notice that zoom may change internally by fitting map bounds or scrolling the mouse wheel.
- listers - it's the object representing map events listeners its properties are names of google.Map events and values are callbacks which is called after event fires.
const listeners = {
click: () => console.log("Map clicked"),
zoomed_out: () => console.log("Map zoomed out")
};
Main concept
Map component is designed to be easily extendable with other map features.
It provides the context (MapContext
) which is responsible for transferring map object as map and Google Maps global object as google
and it's available to all children elements which are map context consumers MapContext.Consumer
.
It's also design to be fully declarative
This approach should provide you a way for attaching new features to the map with simple composition
<Map
google={google}
options={this.state.mapOptions}
listeners={this.state.listeners}
>
<FancyMarker position={this.state.fancyMarkerPosition} />
<AmazingPolygon border={this.state.amazingPolygonBorder} />
</Map>
In above example FancyMarker
and AmazingPolygon
are map features
and became a map members thanks to compositional approach and being a map context consumers.
This approach also ensure that only components that are inside the particular map
may appear on context map instance - it helps to keep code representing map easy to reason about and clean.
MapItem
It's HOC that provides a wrapped component with map instance and google global object. It uses MapContext consumer to pass context data to wrapped component:
render() {
return (
<MapContext.Consumer>
{({ google, map }) => {
const options = { ...this.props.options, map };
return <Item {...this.props} google={google} options={options} />;
}}
</MapContext.Consumer>
);
}
Easiest way for creating map feature is to use this HOC with component that expects google
and map
as a properties.
MapMarker
MapMarker is a component that it's created by MapItem
HOC wrapping Marker
component.
NOTE: It does not render anything - it returns null
from its render method.
- Marker - it's just component that takes
map
andgoogle
along withoptions
as its props. It listens to properties change and updates its internal state accordingly. It's main purpose is to add new instance of google.maps.Marker to map passed to the component as a property. All behavior of this components relays on its props - it does not import any external state by ES6 modules or any other way. Thanks to this it keeps testing easy. - MapItem - as described above its responsibility is to provide Marker with
google
andmap
instances byMapContext.Consumer
.
GoogleApi
GoogleApi is render props based component. Its responsibility is to pass global google
object to rendered components. It communicates with existing DependencyLoader
instance to make sure that https://maps.googleapis.com/maps/api/js
script is loaded, then it passes google object as render function argument. It allows for lazy loading of google maps script and keeping WorldMapViz as the only component that must be imported in order to show map on the screen.
Examples:
You can pass any type of component to render function - GoogleApi does not render any additional components by itself.
const config = { key: "YOUR_API_KEY" }
//...
<GoogleApi
apiConfig={config}
render={google => <MyComponent google={google} />}
/>
DependencyLoader
DependencyLoader class is responsible for async loading of external dependencies.
By calling load
method of the loader and passing the script path
as an argument, you will be able to add new external dependencies asynchronously. Load method returns a promise which resolves when script loading ends with success and rejects when it throws an error.
Every DependencyLoader
instance keeps tracking of scripts paths added by itself. However if you create a multiple instances of DependencyLoader
it's possible to load the same script twice.
NOTE:
This method interacts with DOM - when you call load method, DependencyLoader creates new script tag under body element.
Examples:
If you want to use existing loader (preferred way) just import it from library root
import { loader } from "world-map-viz";
const src = "https://path_to_script.js";
loader.load(src).then(() => console.log("script loaded"));
If you want to create new loader, import the DependencyLoader class from the root module:
import { DependencyLoader } from "world-map-viz";
const loader = new DependencyLoader(document);
const src = "https://path_to_script.js";
loader.load(src).then(onScriptLoaded, onScriptFailed);
Although it's not recommended to create new instance of loader - in most cases it's not needed as you can use existing one.