Code Monkey home page Code Monkey logo

fredrikaugust / atlas Goto Github PK

View Code? Open in Web Editor NEW
2.0 3.0 0.0 2.68 MB

A Google Maps React library. Written because I was dissatisfied with fullstackreact/google-maps-react. Will have focus on minimal rerenders, and trying to rely as much as possible on the Google Maps Javascript API (v3).

Home Page: https://fredrikaugust.github.io/atlas/

HTML 1.83% JavaScript 38.23% TypeScript 57.08% CSS 2.86%
google-maps react typescript maps google-maps-javascript gmaps google-api

atlas's Introduction

Atlas

atlas the greek god

A Google Maps React library. Written because I was dissatisfied with fullstackreact/google-maps-react. Will have focus on minimal rerenders, and trying to rely as much as possible on the Google Maps Javascript API (v3).

NPM JavaScript Style Guide

Live demo

Notes

  • google.maps.LatLngLiteral is just an object of type { lat: number, lng: number }

Install

yarn add reactive-atlas

Usage

API Provider

First of all, you have to setup the global API provider. This is required by the library to work. I recommend you wrap the highest common component of all components that require access to the map with this.

import { GoogleAPIProvider } from "reactive-atlas";

const Root: React.FC = props => (
  <GoogleAPIProvider apiKey="API_KEY">{props.children}</GoogleAPIProvider>
);

useGoogle

This is a hook that returns a google object containing all the methods exposed to us. Has to be used in a component that is a child of GoogleAPIProvider;

import { useGoogle } from "reactive-atlas";

const ComponentThatUsesGoogleAPI: React.FC = props => {
  const google = useGoogle();

  // ...
};

Map

The map is the most important object. It has to be a child (though not direct) of GoogleAPIProvider.

The required options are zoom and center. A number (0-18 inclusive), and google.maps.LatLng or google.maps.LatLngLiteral, respectively.

import { Map, useGoogle } from "reactive-atlas";

const Globus = () => {
  const google = useGoogle();

  return <Map options={{ zoom: 8, center: new google.maps.LatLng(1, 2) }} />;
};

All Markers and other elements should be children of a map, and you should not nest Maps.

Marker

The marker is a common object in maps. It has to be a child of a Map.

import { Map, Marker, useGoogle } from "reactive-atlas";

const Globus = () => {
  const google = useGoogle();

  return (
    <Map options={{ zoom: 8, center: new google.maps.LatLng(1, 2) }}>
      <Marker
        options={{
          position: new google.maps.LatLng(63, 10),
          title: "Hello, World!",
          label: "B"
        }}
      />
    </Map>
  );
};

InfoWindow (and ref forwarding)

The InfoWindow can be handy if you want to display extra information about e.g. a Marker.

import { InfoWindow, Marker, Map, useGoogle } from "reactive-atlas";

const IWExample = () => {
  const ref = React.useRef<Marker>();
  const [open, setOpen] = React.useState(false);

  return (
    <Map options={{ zoom: 8, center: new google.maps.LatLng(1, 2) }}>
      <Marker
        ref={ref}
        options={{
          position: new google.maps.LatLng(63, 10),
          title: "Hello, World!",
          label: "B"
        }}
        eventHandlers={[["click", () => setOpen(o => !o)]]}
      />

      <InfoWindow
        open={open}
        setOpen={setOpen}
        anchor={() => ref.current.marker}
      >
        <p>Hello, World!</p>
      </InfoWindow>
    </Map>
  );
};

As you can see, you can pass a ref to the Marker, and later get out the underlying marker property.

Circle

Exactly the same usage as Marker.

Required option keys are radius: number, and center: google.maps.LatLng | google.maps.LatLngLiteral.

import { Map, Circle, useGoogle } from "reactive-atlas";

const Globus = () => {
  const google = useGoogle();

  return (
    <Map options={{ zoom: 8, center: new google.maps.LatLng(1, 2) }}>
      <Circle
        options={{
          center: new google.maps.LatLng(63, 10),
          radius: 128000
        }}
      />
    </Map>
  );
};

Example of resizable and movable circle

First you have to wrap it in a Provider and Map of course.

Create an event handler which simply prints the new location and radius.

const circleChangePosRadius = circle =>
  console.log(
    `Circle is at ${circle
      .getCenter()
      .toString()} with radius ${circle.getRadius()}.`
  );

Wire it up to print pos/radius every time the radius or center changes.

<Circle
  options={{
    editable: true,
    radius: 100000,
    center: new google.maps.LatLng(63, 10)
  }}
  eventHandlers={[
    ["radius_changed", circleChangePosRadius],
    ["center_changed", circleChangePosRadius]
  ]}
/>

The same principles would be used when making a Marker draggable; just replace radius_changed/center_changed with dragend.

Events

To retain as much of the original code as possible from the google API, I've decided to opt for a bit strange event handling. Instead of doing like google-maps-react (the reason I'm making this library) and using "standard" HTML-like handlers (i.e. onCenter_changed (the weird combination of camelCase and snake_case is because google uses snake-case, and HTML uses camelCase)), I've opted to use a list of event handlers you'd like to attach to the element. This property can be used on Map, Marker, and Circle (as of now).

To remove an event handler, simply remove the entry from the array of handlers, and the library will remove the listener. It will also clean up all listeners when unmounting.

The first parameter in the callback function is the object you're operating on, so in the next example, it's a marker, but if you were to add a listener to a circle, it would be the circle. This allows you to operate directly on the google API, which might be desirable.

The second parameter is a list with one of the following;

  1. Nothing, i.e. []
  2. undefined, i.e. [undefined]
  3. The event (e.g. MouseEvent), i.e. [MouseEvent]

This is a bit strange, but it works quite well. I believe it was intended for possible expansion, so that you could pass more than one event.

import { Map, Marker, useGoogle } from "reactive-atlas";

const Globus = () => {
  const google = useGoogle();

  return (
    <Map options={{ zoom: 8, center: new google.maps.LatLng(1, 2) }}>
      <Marker
        options={{
          position: new google.maps.LatLng(pos, pos)
        }}
        eventHandlers={[
          [
            "click",
            (marker, evt) => {
              // Make it jump!
              marker.setAnimation(google.maps.Animation.BOUNCE);
              setTimeout(() => marker.setAnimation(null), 500);
            }
          ]
        ]}
      />
    </Map>
  );
};

Bounds

Often times, you want to specify the bounds of the place you want to see.

You can do this using the bounds prop on Map. Simply send in a google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral object, and it will scale to that area. If you change the bounds, the map will fit to the new area and pan there.

Styling

For now, there isn't really much styling on the map. It's container is set to flex-grow: 1, which means that you should try to use flex to control the positioning.

License

MIT ยฉ fredrikaugust

atlas's People

Contributors

dependabot[bot] avatar fredrikaugust avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

atlas's Issues

Update README

Love the library, but I think it could be helpful with a more in-depth README. The docs are ๐Ÿ”ฅ though.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.