react-offline-map

React component using svg-pan-zoom to view maps without internet connection

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
react-offline-map
020.3.04 years ago4 years agoMinified + gzip package size for react-offline-map in KB

Readme

React Offline Maps
This module allows users to create maps without any internet connectivity - simply using overlays of images.
It makes use of svg-pan-zoom to display this map in a very user-friendly way.

Install

NPM

npm install --save react-offline-map

Props

|Prop|Default|Type|Description| |-----|------|-----|-----| | width | required | Number | Width of the viewer displayed on screen | | height | required | Number | Height of the viewer displayed on screen | | mapQuality | 'medium' | String | Creates a map of low, medium or high quality | | images | | Array | Images to be displayed on the screen | | text | | Array | Text to be displayed on the screen | | polylines | | Array | Polylines to be displayed on the screen | | circles | | Array | Circles to be displayed on the screen | | buttons | | Array | Buttons to be displayed on the screen | | polygons | | Array | Polygons to be displayed on the screen | | showWorldMap | true | bool | Decides whether background includes world map | | initialPos | {'lat': 0, 'lng': 0, 'zoom': 1} | Object | Sets the initial position of the viewer | | bounds | {'topLat': 90, 'topLng': -180, 'bottomLat': -90, 'bottomLng': 180} | Object | Sets the bounds for a viewer | | onClick | function | func | Allows a callback function. Returns Evt in form {lat: latitude of click, lng: longitude of click, evt: mouseEvent |

NOTE: all coordinates given in Lat/Long (UTM not accepted)

mapQuality
must be a string of value 'low', 'medium' or 'high'. No other options
images
in form:
{'url': String, 'topLat': num, 'topLng', num, 'bottomLat', num, 'bottomLng': num, ...,
such that top left point of image is at coordinate {topLat, topLng}, bottom left of image is at coordinate {bottomLat, bottomLng}
polylines
in form:
{'points': "lat1,lng1", "lat2,lng2", lat3,lng3", ..., 'color': String, 'width': num}, ...,
where the first line will draw points between coordinates {lat1,lng1}, {lat2,lng2}, {lat3,lng3}, ...
circles
in form:
{'lat': num, 'lng': num, 'r', num, 'fill', String}, ...,
such that each circle is centred at coordinate {lat,lng} with radius r
polygon
in form:
{'points': "lat1,lng1", "lat2,lng2", lat3,lng3", ..., 'fill': String}, ...,
where the first polygon will draw points with coordinates {lat1,lng1}, {lat2,lng2}, {lat3,lng3}, ... and filled using fill color.
This is essentially the same as polyline, but the shape is filled.
buttons
in form:
{'name': String, 'lat': num, 'lng', num, 'zoom', num}, ...,
such that a button is created with title 'name' (same as {button.name}).
When clicked, button will jump the viewer to coordinate {lat,lng}, with zoom=button.zoom.
bounds
Helps with rendering if, for example, you only want to view a very small area on the map. Shows only a portion of the map. Eg. If you just want to view UK, you would put bounds={{'topLat': 60, 'topLng': -15, 'bottomLat': 50, 'bottomLng': 5}} NOTE: "top" and "bottom" refer to measurements at the top-left and bottom-right corners of an image respectively.
Therefore, although it may seem counter-intuitive, topLat > bottomLat and bottomLng > topLng. In a normal map (default), top-right corner will be (90,-180) and bottom-right will be (-90,180) -- measurements in form (lat,long).
Therefore, default values are {'topLat': 90, 'topLng': -180, 'bottomLat': -90, 'bottomLng': 180}.

Examples of Use

Most Basic Implementation

import React  from 'react';
import Map from 'react-offline-map'

class Basic extends React.Component {
    return (
        <div>
            <Map width={800} height={600} />
        </div>
    
}

Advanced

import React  from 'react';
import Map from 'react-offline-map'
import iraq from '../images/iraq.png';
import sanfran from '../images/sanfran.png';
import mojave from '../images/mojave.png';
import baja from '../images/baja_peninsula.png';
import bajaZoom from '../images/baja_peninsula_zoom.png';


class Advanced extends React.Component {
    constructor(props) {
        super(props);
        this.state = ({
            showWorldMap: true
        })
    }

    updateMap = () => {
        this.setState({
            showWorldMap: !this.state.showWorldMap
        })
    };
    
    printClick = (event) => {
        console.log("CLICK");
        console.log(event);
    };
    
    render() {
        var images = [
            {'url': mojave, 'topLat': 35.184619089603586, 'topLng': -116.19619200291318, 'bottomLat': 35.173016651002655, 'bottomLng': -116.18129480877964},
            {'url': iraq, 'topLat': 33.61611111, 'topLng': 44.09638889, 'bottomLat': 33.01611111, 'bottomLng': 44.69638889},
            {'url': sanfran, 'topLat': 38.28555556, 'topLng': -122.80972222, 'bottomLat': 37.28555556, 'bottomLng': -121.81000000},
            {'url': baja, 'topLat': 32.533305, 'topLng': -117.123229, 'bottomLat': 22.837566, 'bottomLng': -109.396867},
            {'url': bajaZoom, 'topLat': 32.533305, 'topLng': -117.123229, 'bottomLat': 31.981218, 'bottomLng': -115.213926}
        ];

        var averageLatMojave = (35.184619089603586 + 35.173016651002655) / 2;
        var averageLngMojave = (-116.19619200291318 + -116.18129480877964) / 2;

        var averageLatIraq = (33.61611111 + 33.01611111) / 2;
        var averageLngIraq = (44.09638889 + 44.69638889) / 2;

        var averageLatSanFran = (38.28555556 + 37.28555556) / 2;
        var averageLngSanFran = (-122.80972222 + -121.81000000) / 2;

        var averageLatBaja = (32.533305 + 22.837566) / 2;
        var averageLngBaja = (-117.123229 + -109.396867) / 2;

        var averageLatBajaZoom = (32.533305 + 31.981218) / 2;
        var averageLngBajaZoom = (-117.123229 + -115.213926) / 2;

        var buttons = [
            {'name': 'Example Zoom 1: Baja (x10)', 'lat': averageLatBaja, 'lng': averageLngBaja, 'zoom': 10},
            {'name': 'Example Zoom 2: Baja zoom (x100)', 'lat': averageLatBajaZoom, 'lng': averageLngBajaZoom, 'zoom': 100},
            {'name': 'Example Zoom 3: San Francisco (x200)', 'lat': averageLatSanFran, 'lng': averageLngSanFran, 'zoom': 200},
            {'name': 'Big zoom: Iraq (x400)', 'lat': averageLatIraq, 'lng': averageLngIraq, 'zoom': 400},
            {'name': 'Extreme zoom: Mojave desert (x20000)', 'lat': averageLatMojave, 'lng': averageLngMojave, 'zoom': 20000}
        ];

        var circles = [
            {'lat': 32.1322, 'lng': -116.3452, 'r': 0.1, 'fill': 'red'},
            {'lat': 32.1022, 'lng': -115.7452, 'r': 0.1, 'fill': 'red'},
            {'lat': 32.2722, 'lng': -115.8252, 'r': 0.05, 'fill': 'red'},
        ];

        var polylines = [
            {'points': ['32.1322,-116.3452', '32.1022,-115.7452', '32.2722,-115.8252', '32.1322,-116.3452'], 'color': 'blue', 'width': 0.05},
            {'points': ['35.177319,-116.194', '35.18,-116.192', '35.177319,-116.19', '35.18,-116.188', '35.177319,-116.186'],
                'color': 'blue', 'width': 0.00005},
        ];

        var polygons = [
            {'points': ['35.179319, -116.1834', '35.181319, -116.1834', '35.181319, -116.1854', '35.179319, -116.1854'], 'fill': 'yellow'}
        ];

        return (
            <div className="App">
                <button onClick={this.updateMap}>Toggle world map</button>
                <Map
                    images={images}
                    width={window.innerWidth * 0.9}
                    height={window.innerHeight * 0.9}
                    buttons={buttons}
                    showWorldMap={this.state.showWorldMap}
                    mapQuality={'high'}
                    circles={circles}
                    polylines={polylines}
                    polygons={polygons}
                    handleClick={this.printClick}
                />
            </div>
        );
    }
}

export default Advanced;


Additions?

This is still a very new project, and there's many more features I could add if people feel they are necessary.
Feel free to open an issue with any bugs or enhancements you think I should work on!