mapview-js
Interactive map viewer with 2D and 3D support.
Local Usage
To run your own instance of the demo page (to test how things will look if you make changes in CMS, for example) just follow these steps:
- Clone the repo
npm install
- (Optional) If you want to point to staging, open examples/index.js and add
baseUrl: https://api-staging.mappedin.com/1/,
to the options
object in the doInit
functionnpm run build
(or npm run build-debug
if you want non-minified code)
- If you are going to be modifying mapview.js, either do
npm run build-debug
every time you want to test, or install webpack globally with npm install webpack -g
and then run webpack --watch
so does a quick partial rebuild automatically every time you save.
- Start a web server in this directory. If you don't have one, run
npm install http-server -g
and then just do http-server
- Open
http://127.0.0.1:8080/examples/
(or whatever your local server is running on) - Put your credentials and venue slug in the settings box on the left and hit submit.
If you need credentials, or have any other questions. talk to Paul.
You can also store your credentials- copy MappedinConfig.template.js
to MappedinConfig.js
and put the keys there.
Integration
The demo is useful for testing, shows how the mapview is supposed to be used, and does some neat demos. However, you probably want to actually integrate mappedin.js into your application itself. It is built to either be script tagged or required in.
To setup the map view, you must first perform a test to determine whether the browser can handle 3D or not, or force the mode of the viewer. Either way, first setup an init function that can be called in either situation.
var init = function(error, success) {
Mappedin.init(options, function(error, success) {
if (error) {
console.log('Mappedin error', error);
}
else {
initWithData(success);
}
}
}
We wrap the Mappedin.init
function in our own because the callback in the upcoming functions passes in the error
and success
parameters. This way we can pass in an options object as well. The options object contains your access info, API fields to fetch and things like which venue and perspective you want to work with.
The easiest way to handle the cases is to read a parameter and use a switch statement to get the program going. In this example, the parameter forceMode
is taken from the URL, and uses the init
function from above.
switch(forceMode) {
case '2d':
case '2D':
Mappedin.force2D(init);
break;
case '3d':
case '3D':
Mappedin.force3D(init);
break;
case 'test':
Mappedin.forceTest(canvas, init);
break;
default:
Mappedin.test3D(canvas, init);
}
If successful, success
in init
will contain the data you want to proceed with. You can access it in the callback like so:
function initWithData(response) {
var data = response._data;
In this function we will also call for the map view.
function initWithData(response) {
data = response._data;
var mapViewOptions = {
onDataLoaded: initPostMapLoaded
};
mapView = new Mappedin.MapView(canvas, data, mapViewOptions);
}
The MapView constructor takes your container (just a div
, you can use document.getElementById
or similar to access it), your data, and an options object. Options are optional, just pass a null
to use the defaults. One useful option is the onDataLoaded
callback to work with when your maps and data are all ready to go.
In your callback you have a chance to override some functions to create the behaviour you want. Most notably, you will want to override onPolygonClicked
and onNothingClicked
.
function mapLoaded() {
mapView.onNothingClicked() {
mapView.clearAllPolygonColors();
}
mapView.onPolygonClicked = function(polygon) {
mapView.clearAllPolygonColors();
mapView.setPolygonColor(polygon, 0xff0000, true);
return false;
}
}
This is also the place you want to define your interactive polygons. To do this, we can just simply loop through the locations and their polygons, using MapView's addInteractivePolygon
. Typically these will be polygons that have a location associated with them, though you may also want to look at polygons that have an entrance node. The latter should be a superset of the former, including polygons that are currently vacant.
var locations = data.locations;
for (var i = 0, iLen = locations.length; i < iLen; ++i) {
var location = locations[i];
var polygons = location.polygons;
for (var j = 0, jLen = polygons.length; j < jLen; ++j) {
var polygon = polygons[i];
mapView.addInteractivePolygon(polygon);
}
}
This should be enough to get a basic map view running.
Helper Functions
One thing useful in creating custom behaviours in your map view is being able to get specific data when you need it. These functions utilize lodash's find
function to sift through the data. Since we don't need most of the library, it is useful to only include the pieces that do get used. In these examples, the program is compiled by Babel and is using ES6 syntax. We include find via import find from 'lodash.find'
.
const getLocationByPolygonId = (pid) => {
return find(venue.locations, (location) => {
return find(location.polygons, { 'id': pid });
});
};
const getLocationById = (lid) => {
return find(venue.locations, { 'id': lid });
};
const getPolygonInLocationId = (pid, location) => {
return find(location.polygons, { 'id': pid });
};
const getNodeByPolygonMap = (mid, location) => {
return find(location.nodes, { 'map': mid });
};
const getMapById = (mid) => {
return find(venue.maps, { 'id': mid });
};
Drawing Directions
Part of the location data structure is a directionsTo
function to get data we can use to draw paths on our maps. To get the data you can use two location objects and the API will figure out the best entrance nodes to depart from, and navigate to. This example assumes we have already found departure
and destination
and they are location objects. options
is assumed to be null
in this example, but you can pass in the field accessible
as true
to get accessible directions.
function drawDirections(error, data) {
if(!error) {
var firstMap = getMapById(data.path[0].map);
mapView.setMap(firstMap);
mapView.removeAllPaths();
var pathOptions = {
color: 0x007afb,
radius: 12
};
mapView.drawPath(data.path, pathOptions);
}
}
departure.directionsTo(destination, options, drawDirections);