The QMaps JavaScript library is a series extensions to the Google Maps API for the purpose of interactive map editing and annotation. It's an abstraction of the code which powers quikmaps.com.
QMaps is designed for the following:
QMaps is made available under the Creative Commons Attribution-NonCommercial-ShareAlike licence, version 2.5. This means you may use the software in any non-commercial endeavour, provided you make attribution to the author / licensor. For commercial endeavours, contact info@spatialnorth.com.
Dependencies: Google Maps API v2.50+, prototype 1.5.0, and scriptaculous 1.7.0. Prototype and Scriptaculous carry open licences, but you'll need to get your own Google Maps API key and agree to the Google Maps API Terms of Use.
Download the code: qmaps_v0.1.tar.gz or qmaps_v0.1.zip. Extract it into a directory on your web server and follow the instructions in the README file.
Class reference: here. When using QMaps, those classes which extend GMaps classes should at all times be used in place of their GMaps superclasses.
Examples: Lots here.
Help / Questions: Email info@spatialnorth.com, or, for now, leave a comment here.
The remainder of this document assumes a reasonable familiarity with the Google Maps API. If you're not familiar with the GMaps API, you might want to browse Google's excellent set of documentation.
A map editor very similar to quikmaps.com/new is included with the library and can be invoked with just a couple lines of code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>QMaps :: Editor Example</title> <script src="http://maps.google.com/maps?file=api&v=2&key=abcdefg" type="text/javascript"></script> <script src="QMaps_google_full.js" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ function load() { // just put these lines in a load handler var editor = new QMapEditor($('editor')); editor.map.setCenter(new QLatLng(53, -113), 8); } //]]> </script> </head> <body onload="load()" onunload="GUnload()"> <div id="editor" style="width: 800px; height: 600px"></div> </body> </html>
Try it here. If you need assistance working with the editor, try the quikmaps help page.
QMapEditor is built entirely on top of the QMaps' QMap, QConfig, and QUtils objects, with Nomadic Functions' colour picker and Google's geocoder squeezed in. As you'll see later in the document, you can build something similar.
QMaps has a number of methods for pulling data out of the editor for later display. Supported are a QMaps-specific XML format, JSON, KML (for Google Earth), and GPX (XML-based GPS transfer format). QMaps also supports a JavaScript object format. In all cases the export contains information for reconstructing both the current map state (lat/lng center, zoom, map type) and the current map overlays.
The methods are interest are editor.map.getXml, editor.map.getKml, editor.map.getGpx, editor.map.getObject, and editor.map.getJSON.
// returns an XML document as string var xml = editor.map.getXml(); // returns a KML document as string var kml = editor.map.getKml(); // returns a GPX document as string var gpx = editor.map.getGpx(); // returns a JavaScript object var js_obj = editor.map.getObject(); // returns a JavaScript object serialized as JSON var json = editor.map.getJSON();
You can test the export routines here. More documentation on the output formats may appear later; for now just inspect the function return values.
You can import data into the Quikmaps editor using editor.map.importXml, editor.map.importJSON, editor.map.importObject, or by using Google maps API methods.
var editor = new QMapEditor($('editor')); // an example xml string var xml = '<data><meta x="-112.9998" y="53.1205" zoom="8" maptype="2" /><overlays>'; xml += '<o type="textmarker" point="(53.0709,-113.0383)" ><cont><![CDATA[my label]]></cont></o>'; xml += '<o type="marker" point="(53.0280,-113.1536)" icon="http://quikmaps.com/images/default/marker_34_white.png" width="20" height="34" >'; xml += '<cont><![CDATA[My house!]]></cont></o>'; xml += '<o type="draw" points="(53.1269,-113.5107),(53.1368,-112.3406),(52.7462,-112.3956),(52.8525,-113.5546)" colour="#003399" width="5" />'; xml += '<o type="scribble" points="(52.9420,-112.7581),'; xml += '(52.9420,-112.7691),(52.9420,-112.7801),(52.9320,-112.8021),'; xml += '(52.9254,-112.8131),(52.9089,-112.8240),(52.8956,-112.8295),'; xml += '(52.9254,-112.7636),(52.9254,-112.7691)" colour="#003399" width="5" />'; xml += '</overlays></data>'; editor.map.importXml(xml); // an example json string var json = "{overlays:[{type:'marker',point:[52.9022,-113.6151],icon:'http://quikmaps.com/images/default/marker_34_white.png',"; json += "width:20,height:34,data:'my house!'}],meta:{zoom:8,maptype:2,x:-113,y:53}}"; editor.map.importJSON(json); // add some overlays manually map.addOverlay(new QMarker(new QLatLng(38, -123), "My house!")); map.addOverlay(new QTextMarker(new QLatLng(36, -123), "hello, world")); map.addOverlay(new QPolyline([new QLatLng(36, -121), new QLatLng(37, -122), new QLatLng(38, -124)])); // will contain all the overlays, with map center / zoom / maptype reflecting json meta data var xml = editor.map.getXml();
For convenience QMaps also provides editor.map.setXml, editor.map.setJSON, and editor.map.setObject, each of which clears all map overlays before importing the data.
QMapEditor contains a static array which defines the URLs of marker images displayed in the right-hand tools panel. Therefore, you can change the markers by overriding this array before instantiating a QMapEditor. For example:
var base = "http://quikmaps.com/images/fast_assorted/"; QMapEditor.MARKER_LIST = [ base+'ball.png', base+'bike.png', base+'book.png', base+'bowling.png', base+'bug.png', base+'car.png', base+'car2.png', base+'cat.png', base+'dog.png', base+'flower.png', base+'guitar.png', base+'tree.png' ]; var editor = new QMapEditor($('editor')); editor.map.setCenter(new QLatLng(53, -113), 8);
Try it out here.
The Quikmaps editor would be useless without the ability to render the maps in a non-editable fashion - to display the map for all to see!
To do so, instantiate a QMap object, and import data.
// an example xml string var xml = '<data><meta x="-112.9998" y="53.1205" zoom="8" maptype="2" /><overlays>'; xml += '<o type="textmarker" point="(53.0709,-113.0383)" ><cont><![CDATA[my label]]></cont></o>'; xml += '<o type="marker" point="(53.0280,-113.1536)" icon="http://quikmaps.com/images/default/marker_34_white.png" width="20" height="34" ><cont><![CDATA[My house!]]></cont></o>'; xml += '<o type="draw" points="(53.1269,-113.5107),(53.1368,-112.3406),(52.7462,-112.3956),(52.8525,-113.5546)" colour="#003399" width="5" />'; xml += '<o type="scribble" points="(52.9420,-112.7581),'; xml += '(52.9420,-112.7691),(52.9420,-112.7801),(52.9320,-112.8021),'; xml += '(52.9254,-112.8131),(52.9089,-112.8240),(52.8956,-112.8295),'; xml += '(52.9254,-112.7636),(52.9254,-112.7691)" colour="#003399" width="5" />'; xml += '</overlays></data>'; // create a map and import the xml data map = new QMap($('map')); map.importXml(xml);
Try it out here. You can alternatively use map.importJSON, map.importObject, or any of the map.setXXX routines.
QMap extends GMap2, and, as such, responds to all the methods, event handlers, etc... you would otherwise use with Google's API. This includes adding markers, polylines, and polygons.
You can create an editable QMap by instantiating with option {editable: true}. There are currently three editing modes: scribble (QMap.SCRIBBLE), draw lines (QMap.DRAW), and markers / pointer (QMap.MARKERS). Markers / pointer mode is the default.
A few basic examples will be sketched here; those interested in building more powerful custom map editors should consult the class documentation.
To scribble lines, as in quikmaps.com's 'scribble' mode, use the map.setDrawingMode function. You can also set the line colour and width.
var map = new QMap($('map'), { editable:true }); map.setCenter(new QLatLng(53, -113), 8, Q_NORMAL_MAP); map.setDrawingColour("#222222"); map.setDrawingWidth(8); map.setDrawingMode(QMap.SCRIBBLE);
Try it here.
'Draw lines' mode is also initialized with map.setDrawingMode.
var map = new QMap($('map'), { editable:true }); map.setCenter(new QLatLng(53, -113), 8, Q_NORMAL_MAP); map.setDrawingMode(QMap.DRAW);
Try it here.
QMaps interprets <img> tags of class "mapicon" as a custom markers and will enable those images for dragging onto the map. Images can be placed anywhere on the page -- on quikmaps.com the logo is actually a custom marker (our little easter egg...).
In addition, DOM elements of class "maptext" are interpreted as custom text marker triggers and will be enabled for dragging onto the map.
In both cases, draggable elements must each have unique "id" attributes.
Map initialization:
var map = new QMap($('map'), { editable:true }); map.setCenter(new QLatLng(53, -113), 8, Q_NORMAL_MAP);
HTML body excerpt:
<p> <img class="mapicon" id="marker1" src="marker_20_red.png" /> <img class="mapicon" id="marker2" src="marker_20_green.png" /> <img class="mapicon" id="marker3" src="markers/default/start.png" /> <span class="maptext" id="maptext">text label</span> </p>
Image (<img>) tags of class "eraser" automatically become draggable erasers. Drag the eraser over map objects and watch them disappear. For example:
<img class="eraser" src="/eraser.gif" /> <div id="map" style="width: 600px; height: 400px"></div>
Try it here.
We'll include some custom markers, a text label trigger, and a mode switcher.
Map initialization code
map = new QMap($('map'), { editable:true }); map.setCenter(new QLatLng(53, -113), 8, Q_NORMAL_MAP); map.setDrawingMode(QMap.MARKERS);
HTML body code
<body onload="onLoad()"> <div id="map" style="width:600px; height: 400px;"></div> <p> <img class="mapicon" id="marker1" src="marker_20_red.png" style="margin:5px;" /> <img class="mapicon" id="marker2" src="marker_20_green.png" style="margin:5px;" /> <img class="mapicon" id="marker3" src="start.png" style="margin:5px;" /> <span class="maptext" id="maptext">text label</span> <select onchange="map.setDrawingMode(this.value)"> <option value="markers">Pointer</option> <option value="scribble">Scribble</option> <option value="draw">Draw</option> </select> </p> <p><a href='#' onclick="alert(map.getXml()); return false;">map data</a></p> </body>
Try it here.
The following GMaps API classes have been extended in QMaps. At all times you should use the QMaps versions, as they contain functionality extensions necessary for editing and viewing QMaps-styled maps.
The following GMaps classes / objects are extended by QMaps:
In editable modes, QMaps runs very fine on Internet Explorer versions 6+ and Firefox versions 1.5+. Opera support is rather sketchy at the moment and Safari hasn't been well-tested. Non-editable QMaps are supported on all browsers supported by Google Maps.
To display polylines in Internet Explorer, you'll need to ensure you've included the VML namespace. For more information, check out Google's explanation.