Table of Contents
Recently I was revisiting the article Silverlight - Creating Image Map with Hotspots that I wrote couple years ago using Silverlight and Expression Blend 3.0. I decided to redo it using HTML5. This brief tutorial demonstrates on how to implement the interactive map using HTML5, KineticJS and jQuery.
Shown in figure 1 are the files in the sample project. The images folder contains all the flag images and InteractiveMapData.js file contains all the map information. InteractiveMapPath.htm and InteractiveMapPoint.htm includes a sample interactive map using SVG path and point respectively. KineticJS is an HTML5 Canvas JavaScript library that extends the 2d context by enabling high performance path detection and pixel detection for desktop and mobile applications.
Figure 1
You can use expression blend to create the SVG path, please refer to Silverlight - Creating Image Map with Hotspots for more information. In the InteractiveMapPath.htm example, I reused the path drawings from the previous tutorial. If you notice it closely the fill and stroke are a little bit off compare to the other example. I’m very positive this wouldn’t happen if I redraw the path again. There are several free tools out there you can use to draw the path data but the one I found the most productive one is from aviary. Here is a brief tutorial on how to use it to generate and utilize the path data.
- Click on Start a new Phoenix link creation under Launch Phoenix image
- A new window will open, click on Load an image file link
- You can browse for the image on your PC or provide an absolute link to the picture and hit the upload button.
- Right click the newly created layer and select Push layer to raven
Figure 2
- It will bring up another window with a pen tool similar to figure 3
Figure 3
- Select the pen tool (highlighted in yellow) and start to draw the path on the image.
- After you have done drawing the path on the image, click on File, Export, Export to SVG, OK, save the file
- You can open the .svg file using notepad or other HTML editor to view and copy the path data
Another option to create interactive map/image is to use SVG polygon. My favorite is the Online Image Map Editor because this one has an option to zoom in and it very helpful when drawing polygon on a small area.
We will use KineticJS JavaScript library to hook up the event listeners to the shapes on the images. You can find lots of good example on how to utilize the library from HTML5 Canvas Tutorials. I will briefly go through the implementation. Both the implementation in the attached example is about the same. The main difference is that one is using Kinetic.Polygon()and the other using Kinetic.Path() constructor.
Listing 1
var path = new Kinetic.Path({
data: c,
fill: '#fff',
stroke: '#555',
strokeWidth: .5
});
var shape = new Kinetic.Polygon({
points: points,
fill: '#fff',
stroke: '#555',
strokeWidth: .5
});
The div elements inside the body tag are use to hold the image map and the menu. Initially I was planning to use the HTML5 context menu but decided to drop it because the menu element wasn’t supported by many browsers. I ended up using the jQuery to create the menu on mouse click.
Listing 2
<div id="container"></div>
<div id="contextMenu" style="display:none">
<div id="contextMenuH"></div>
<div id="contextMenuB"></div>
</div>
Shown in listing 3 are the mouse events associated with each shape. The JavaScript is very straight forward. Here is a brief explanation of the events. The color will change from white to green when mouse over the shape. You can change it to your favorite color. On mouse out the shape, set the color back to white and hide the tooltip. The tooltip with the country name will appear when moving the mouse along the shape. There is also logic to hide the menu when moving the mouse from one shape to another shape. And last but not least the mouse click event. We are using jQuery to position and generate the menu. The menu composes of country name, flag image and several links related to the selected country.
Listing 3
shape.on("mouseover", function () {
this.setFill('#008000');
this.setOpacity(0.5);
shapesLayer.drawScene();
});
shape.on("mouseout", function () {
this.setFill('#fff');
shapesLayer.drawScene();
tooltipBackground.hide();
tooltip.hide();
tooltipLayer.drawScene();
});
shape.on("mousemove", function () {
var mousePos = stage.getMousePosition();
var x = mousePos.x + 5;
var y = mousePos.y + 10;
drawTooltip(tooltip, x, y, k);
if (previousK !== k) {
previousK = k;
previousSelected = this;
$("[id$='contextMenu']").css({
display: 'none'
});
}
});
shape.on("mousedown", function (e) {
$("[id$='contextMenu']").css({
display: 'inline',
position: 'absolute',
top: e.pageY,
left: e.pageX + 5,
opacity: .8
});
$("[id$='contextMenuH']").html('');
$('<img />').attr('src', area.flag).appendTo($("[id$='contextMenuH']"));
$('<span />').html(k).appendTo($("[id$='contextMenuH']"));
$("[id$='contextMenuB']").html('');
$('<a target="_blank"></a>')
.attr('href', 'http://www.countryreports.org/country/' + k + '.htm')
.html('Country Reports').appendTo($("[id$='contextMenuB']"));
$('<br/><a target="_blank"></a>')
.attr('href', 'http://www.economicexpert.com/a/' + k + '.htm').html('Economy')
.appendTo($("[id$='contextMenuB']"));
$('<br/><a target="_blank"></a>')
.attr('href', 'https://www.cia.gov/library/publications/the-world-factbook/geos/' + area.abbreviation + '.html')
.html('Factbook').appendTo($("[id$='contextMenuB']"));
$('<br/><a target="_blank"></a>')
.attr('href', 'http://www.geohive.com/cntry/' + k + '.aspx')
.html('Global Statistics').appendTo($("[id$='contextMenuB']"));
$('<br/><a target="_blank"></a>')
.attr('href', 'http://en.wikipedia.org/wiki/' + k).html('Wiki')
.appendTo($("[id$='contextMenuB']"));
});
Polygon or Path? I think they both behave the same and didn’t make much different and it depends on the tools that we have.
Recently, I discovered that the sample code HTML5 - Interactive Map using SVG Path/Data was no longer working correctly in Firefox 19.0. The mouseover event was totally off. Initially I thought simply updating the KineticJS library will solve the issue but that was not the case. The reason was because some of the property/method were being removed and replaced in kinetic-v4.3.3. For instance, Layer.draw() is now Layer.drawScene(), setAlpha() is being replaced with setOpacity(), color name is no longer valid and we should use HTML color code, and etc. In kinetic-v3.9.7, we can set the text background color through the Kinetic.Text constructor. But in the latest KineticJS library, we have to group the Rectangle and Text object to create the text with background color. I have updated the source code to use the latest library and everyone is welcome to download it.
I hope someone will find this information useful and make your programming job easier. If you find any bugs or disagree with the contents or want to help improve this article, please drop me a line and I'll work with you to correct it. I would suggest downloading the demo and explore it in order to grasp the full concept of it because I might miss some important information in this article. Please send me an email if you want to help improve this article.
Tested on: Internet Explorer 9.0, Firefox 19.0, Google Chrome 25.0, Apple Safari 5.1.7
06/14/2012: Initial version.
02/24/2013: v02.00.00
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-path-tutorial/
http://www.mobilefish.com/services/image_map/image_map.php
http://www.mobilefish.com/services/image2svg/image2svg.php
http://www.image-maps.com/
http://code.google.com/p/imgmap/
http://www.w3schools.com/svg/svg_path.asp
http://svg-edit.googlecode.com/svn/branches/2.5.1/editor/svg-editor.html
http://advanced.aviary.com/tools/image-editor
http://www.maschek.hu/imagemap/imgmap
http://www.famfamfam.com/lab/icons/flags
HTML5 Interactive Map using SVG Path
HTML5 Interactive Map using Polygon
HTML5_Interactive_Map.zip