By using the mapsuite Javascript API you can embed maps in your websites both for desktop and mobile browsers. You can control the visible section of the map by setting a coordinate or address, define user interaction with the map, add layers with Points of Interest (POIs), search hits or areas, calculate routes and visualize them on the map, and much more. Have a look at our tutorial for a brief overview of the API features.
The API and implementation is plain Javascript, so map applications created by the MapAPI run in all modern browsers without plugins, addons etc. All you need to start is basic Javascript knowledge.
Browser | Version |
---|---|
Mozilla Firefox | 3.0+ |
Apple Safari | 3.1.2+ |
Google Chrome | Current version |
Opera | 10.0+ |
Microsoft Internet Explorer | 6.0+ |
Yes, starting with version 1.1 both iOS (iPhone and iPad) and Android (Webkit based browsers for smart phones and tablets, like the default browser and Chrome) are supported.
These touch gestures can be used to control the map:
Please note that Android does not support multi touch events in browsers before version 3 ("Honeycomb").
Yes, this is possible with this version of the MapAPI. It automatically switches to HTTPS transport if it is loaded by HTTPS.
The API is usually hosted on our servers, so no more hardware resources are required on your side. All our servers are hosted in Germany to provide fast access in Europe.
However if you want to use your own server infrastructure, please contact us at mapapi@infoware.de.
Just send us an e-mail to mapapi@infoware.de. Please include the following details:
In general we tried to make the MapAPI 1.1 as compatible as possible. Most applications can be ported with no or few changes by changing the URL to the new version. You'll probably want to make more changes to use some of the new features like touch gestures, modularization or geolocation.
Here is a list of changes which could break compatibility with your application:
function CustomInfoBubble(map, coordinate, content)
{
IWWindowOverlay.call(this, map, coordinate); /* call constructor of base class */
// your contructor implementation
}
CustomInfoBubble.prototype = new IWWindowOverlay(); /* inherit methods of base class */
CustomInfoBubble.prototype.aMethod = function()
{
// ...
};
CustomInfoBubble.prototype.anotherMethod = function()
{
// ...
};
function CustomControl(map)
{
IWControl.call(this, map, 'CustomControl');
IWDraggable.call(this, this.getContainer(), map.getContainer());
// your contructor implementation
}
CustomControl.prototype = new IWControl();
for (var property in IWDraggable.prototype)
CustomControl.prototype[property] = IWDraggable.prototype[property];
CustomControl.prototype.aMethod = function()
{
// ...
};
CustomControl.prototype.anotherMethod = function()
{
// ...
};
if (navigator.geolocation && navigator.geolocation.getCurrentPosition)
{
// feature is available
}
else
{
// use a fallback
}
The easiest way is to include the core.js, which contains the mapping parts themself, base classes and interfaces, the event system etc. Just insert
<script type="text/javascript" src="http://iw.mapandroute.de/MapAPI-1.1/js/core.js?vnr=[yourVNR]&pnr=[yourPNR]"></script>
into your page and start using the API after an onload event
(or $(document).ready(yourInitHandler) when using jQuery).
Other features like special controls, routing, or touch events for mobile devices, are available in modules. Just load
the modules you want to use to reduce the loaded script size.
Replace your request to mapping.js by core.js to load the core module. Now identify the modules you want to use and add this code after the initialization of the map:
IWEventManager.addListener(IWLoader, 'onmoduleload', function(event)
{
if (event.name == 'touch')
{
// touch module has been loaded, so add touch gestures to the map
if (IWTouchUtils.isTouchScreenAvailable())
{
IWTouchUtils.addTouchGestures(map);
IWTouchUtils.setTouchOptions(map, { autoClearTiles: true, reloadOnMove: false });
}
}
else if (event.name == 'controls')
{
// control module has been loaded, so add some controls to the map
var layer = map.getLayoutManager().getLayer(0);
layer.addControl(new IWZoomButtonControl(map), IWAlignment.BOTTOM, IWAlignment.LEFT, 0, 0);
layer.addControl(new IWBirdsViewControl(map), IWAlignment.BOTTOM, IWAlignment.LEFT, 10, 10);
}
});
// request the loading of two modules
IWLoader.loadModules(['touch', 'controls']);
A detailed example can be seen in mobile.html.
The default behavior zooms into the map on mouse wheel up events and out of the map on mouse wheel down.
If you want to change this for some reason you must disable the default behavior and implement your own handler method. Have a look at the example below which switches zooming directions:
map.getOptions().setMouseWheelAction(IWMapOptions.CONTROL_NONE);
var adapter = new IWMouseWheelAdapter(map, map.getContainer());
IWEventManager.addListener(adapter, 'onmousewheel', function(event)
{
if (event.delta < 0)
map.zoomIn();
else
map.zoomOut();
});
If you wannt a map to fit the window size, you can use the auto resize option. When set to true, the map will always fit the whole browser window.
var map = new IWMap(document.getElementById('map'));
map.getOptions().setSize(iw.windowSize()); // initialize the map with the window size
map.getOptions().setAutoResize(true); // use auto resize to always fit the window
Each map type can be configured by the methods setMinLevel, setMaxLevel and setPreferredLevel. The example below shows how to limit both the minimum and maximum level. In the last line setCenter is called to assure the map shows a valid zoom level (the old level may be out of the new constraints).
map.getCurrentMapType().setMinLevel(5);
map.getCurrentMapType().setMaxLevel(10);
map.getCurrentMapType().setPreferredLevel(8);
map.setCenter(map.getCenter(), map.getZoom());
Using the Kartenverzeichnis-API in a MapAPI application is easy. Just first import the mapsuite API and then the Kartenverzeichnis-API in your page as seen in our example.
As the main class SearchableMap extends IWMap, all your existing code will run without changes after switching to SearchableMap. Just have a look at our test application on how to add more features.
Below is a code snippet. For more details, please have a look at the documentation of IWBounds.
var nw = new IWCoordinate(6.85465, 51.08357, IWCoordinate.WGS84).toMercator(); // north-west of Cologne
var se = new IWCoordinate(7.20694, 50.64929, IWCoordinate.WGS84).toMercator(); // south-east of Bonn
var myBounds = new IWBounds(nw, se);
var coord = new IWCoordinate(7.14512, 50.70001, IWCoordinate.WGS84).toMercator();
myBounds.extendBy(coord);
map.setCenter(myBounds.getCenter(), map.getBoundsZoomlevel(myBounds));
In this example an existing bounds object is extended by another coordinate. If you have an array of coordinates just span a bounds object from the first two and extend it by all of them. Thus you will get a bounds object containing all your coordinates.
In case of a route you can use the bounds object of the route:
map.setCenter(route.getBounds().getCenter(), map.getBoundsZoomlevel(route.getBounds()));
Yes, starting with version 1.1.46 you can set the rendering method to render
by calling
IWRoutingControl.setOptions().
This will render the route as a polyline in an IWMapRenderer, so all rendering attributes for polylines can be used:
var options = {
render: 'renderer',
renderAttributes: {
stroke: 'green',
strokeDashStyle: 'solid',
strokeWidth: 5,
strokeOpacity: 0.8
}
};
var routingControl = new IWRoutingControl(map);
routingControl.setOptions(options);
IWMapRenderer is part of the module graphics
, so you will have to load this module as well!
MapAPI offers several projection-systems to describe positions on a map. The most important systems are:
WGS84 consists of a latitude value and a longitude value to define a certain point on earth. These values base on a spherical shape of the earth. WGS84 is often used to exchange position data between different system. For example, when you get position data from a GPS device.
Note: GPS uses the number format DD.HHMMSS, WGS84 here is used as decimal degrees.
Example: The address "Riemenschneiderstr. 11 in 53175 Bonn" has the WGS84 coordinate lon=7.141260 lat=50.701184, 6 decimal digits is a precision of approx. 1 meter.
Because the WGS84 system is spherical based, it has to be projected to get position data, that fits a planar view (on screen or printer). Map data itself is based on a planar metric system:
MERCATOR coordinates consist of a x-value and a y-value, both in meters. It is easier to use than WGS84: It can be directly mapped on a map (linear scale to pixels), it is easy to calculate distances (Pythagoras: distance = sqrt ( a^2 + b^2 )). This system is also used by other mayor map vendors.
Example: The address "Riemenschneiderstr. 11 in 53175 Bonn" has the MERCATOR x=794961 y=6568605 (metres).
See also the entries in english or german Wikipedia for further information.
Most probably, you can. Mercator and WGS84 coordinates can be passed directly at the instantiation of IWCoordinate objects. Several other projections can be converted to Mercator via IWProjectionClient class. For details, please have a look at Chapter 8 of the tutorial.
As of now we support following projections and conversions:
projection | conversion | projection |
---|---|---|
Mercator | ↔ | WGS 84 |
LCC Europe | ↔ | WGS 84 |
LCC Europe | → | LCC Germany Bessel AKA LCC TAO |
LCC Germany Bessel | → | LCC Europe |
LCC Germany Bessel | → | Mercator |
WGS84 | → | UTM 32 |
For more details, please have a look at the documentation of IWProjectionType. If your desired projection does not exist, simply contact us at mapapi@infoware.de.
The MapAPI can be used with various providers of geodata, covering Germany, european and worldwide countries. Please contact us to find the best data source for your requirements.
As of now mapsuite API supports roadmap, air, hybrid and bird's eye views. The map type is always set by a call to IWMap.setCenter(). To set a new map type, you can use this code snippet:
var type = map.getOptions().getMapTypeByName('hybrid');
map.setCenter(map.getCenter(), map.getZoom(), type);
For more details, please have a look at the documentation of IWMapType.
Yes, if you host your own map servers (which are part of the mapsuite) the layout can be configured in a very flexible way. We provide an application called MapStyler which may be used to design the map layout. Please contact us for more information.
The POIs are managed on backend servers. The selection of POI types, the appearance (i.e. the symbols), the zoom levels on which POIs are visible and more can be configured per application by a web application called MapCMS. Please contact us for details.
We have several types of dynamic POIs available with either dynamic content or dynamic coordinates (or both). Examples are traffic information, weather, filling stations, parking grounds and cinemas. Please contact us for more information.
The map is served as an image cut into several tiles. The browser aligns the tiles together back to a complete map. The tiles have to be loaded from the tile server. The number of tiles loaded depends on the screen size on the client and the number of border tiles which should be loaded additionally.
This number is usually greater than 20 on desktop machines. Standard browsers of today allow 6 parallel connections to one server; or to be more precise, to one subdomain of a domain. The other requests are queued. So the loading speed can be optimized by loading the tiles from different servers, and thus creating more parallel connections. For details please see Parallelize downloads across hostnames.
The MapAPI allows downloads from multiple servers. The load is spread equally among these servers. One tile is loaded always from the same server, so caching within the browser is fully used. To use multiple servers, or multiple subdomains on one server / server pool, you can configure aliases in the XML based MapAPI config file. For a MapAPI hosted on our servers, this already is configured.
Usually map movement should be smooth and there is no need to tweak performance, unless you don't have to support very old browsers or hardware. If your map is to slow you should check if you are using time-consuming calculations on the onmove event of the map, which are fired everytime the map is moved for a single pixel. If this is the case you should check if it is possible to do this on the onmoveend event (which is fired when the map movement is done), so your calculation does not interfere with map movements.
Other settings you should check are the size of the map (is the map larger than the visible part you show on your page?) and the number of tiles which are loaded outside of the visible part of the map (see setBorderTiles(), usually should be 0 or 1).
After the user moved or zoomed the map or changed the map type, new tiles are loaded and old tiles aren't visible any more. These tiles are not immediately removed from the DOM tree but are still available in background in case the user navigates back to this view. Tiles must be removed from the DOM tree because the browser cannot handle unlimited tiles. The strategy how tiles can be removed can be set manually. Three are available:
The removal strategy of the map is defined like this:
map.setRemovalStrategy(new IWTilesRemovalStrategyHarsh());
The MapAPI offers two ways to draw markers on the map. The base class IWOverlay can be used to attach DOM objects to a coordinate on the map. Everytime the map is moved or zoomed it updates these overlays. An example is the class IWMarker, but of course you can implement own classes which extend IWOverlay. Every overlay you add to the map is a DOM object, so adding lots (e.g. thousands) of these objects will result in slower map movements.
In this cases you should think of using layers. The markers in these layers are stored on the server and rendererd to a single image every time the map is moved. This is much faster for large amounts of markers. Examples for layers are POIs and routing layers.
For more detailed descriptions see the chapters on overlays and shapes in the tutorial.
Overlays | Layers | |
---|---|---|
numer of markers | limited (depends on target plattform) | huge amounts (managed on the server) |
flexibility | high (own implementations with HTML, JS, CSS) | low (static images only) |
user interaction | fast (Javascript events) | slow (round-trip-time to server) |
No, you don't have to. All features of the MapAPI can be used from procedural applications as well (unless you want to extend MapAPI classes, of course).
Hoewever, we suggest an object-oriented approach for complex applications as it leads to the same advantages as in other programming languages, like an improved reusability, readability, testability and other benefits.
If you are used to object-oriented languages like C++ or Java, OOP in Javascript won't look familiar to you. For example, there are no classes in Javascript but prototype-based inheritance. Here is a brief overview how OOP can be done with objects, constructor functions and prototypes. For a more detailed introduction see this article on MDN.
The usual way to create an object in Javascript is var x = new Object();
(or the shorter
notation var x = {};
). The first step to introduce a "class" is to write a constructor
function like this:
function Programmer(name)
{
this.name = name;
this.caffeine = 0;
}
When a constructor function is called with new, the newly created object becomes accessible in the function
by the name this
.
Now you can create instances of your class by writing var x = new F();
. The result is an object
(typeof x
will return 'Object') with the properties x and y.
As functions can be assigned to any variable, you can add functions as properties to your class to add methods. Again, use this to access the object and its properties from these functions:
function Programmer(name)
{
this.name = name;
this.caffeine = 0;
this.work = function()
{
if (this.caffeine > 0)
{
console.log(name + ' produces some code');
}
else
{
throw name + ' is out of coffee!';
}
}
this.drinkCoffee = function()
{
console.log(name + ' drinks coffee');
this.caffeine += 5;
}
}
var codeMonkey = new Programmer('Code monkey'); // now create an instance and use it
try
{
codeMonkey.work();
}
catch (e)
{
codeMonkey.drinkCoffee();
codeMonkey.work();
}
Assigning the methods in the constructor has two main disadvantages: The constructor becomes more complex (thus making it slower) and the methods have to be assigned to each object which is instantiated from the class (imagine you need a lot of code monkeys...). A more elegant solution is to use the prototype of the constructor function instead:
function Programmer(name)
{
this.name = name;
this.caffeine = 0;
}
Programmer.prototype.work = function()
{
if (this.caffeine > 0)
{
console.log(name + ' produces some code');
}
else
{
throw name + ' is out of coffee!';
}
}
Programmer.prototype.drinkCoffee = function()
{
console.log(name + ' drinks coffee');
this.caffeine += 5;
}
There are some abstract base classes in the MapAPI which are meant to be extended. For example you can extend IWControl to implement your own controls or IWWindowOverlay to create your own bubbles to display content on the map. Other classes can be extended as well, for example think of an extended version of IWCoordinate which supports your custom coordinate projection.
To extend a class you have to do two steps: Make your constructor call the constructor of the base class, and create the prototype of your constructor as an instance of the base class. Let's have a look at this example:
function CustomCoordinate(x, y, projection)
{
// TODO calculate lat, lon from x, y
IWCoordinate.call(this, lon, lat, IWCoordinate.WGS84); // (1)
}
CustomCoordinate.prototype = new IWCoordinate(); // (2)
CustomCoordinate.prototype.toCustomProjection = function()
{
var wgs84 = this.toWGS84();
var lat = wgs84.getY();
var lon = wgs84.getX();
// TODO calculate x, y from lat, lon
return new IWCoordinate(x, y, 'CustomProjection');
};
This class extends IWCoordinate to support a custom projection. To do this the lines marked with (1) and (2) are important. The first one calls the constructor IWCoordinate on the object "this", i.e. the object which is created by the CustomCoordinate constructor. For details see the documentation of Function.call().
The line marked with (2) makes the prototype of CustomCoordinate an instance of IWCoordinate, thus inheriting all methods and constants defined for IWCoordinate. Now you can use your custom coordinate class as replacement for IWCoordinate, i.e. map.setCenter(new CustomCoordinate(1234, 5678)); will center the map on the WGS84 position corresponding to the coordinate (1234, 5678) in your custom projection.
Copyright 2007-Tue Nov 05 22:04:13 CET 2024 infoware GmbH