And so I decide to create maps using d3.js using this tutorial. The tutorial creates a map of NYC – me I wanted the state of karnataka where I live.
The first piece of code illustrates creating maps using SVG maps.
var length = 300;
var width = 350;
var svg = d3.select('body').append('svg')
.attr('width', width))
.attr('height', height);
var group = svg.append('g');
var NYPath = "M7.0371 120.844l-0.6373 11.9674 … -1.0232 0.1923z”;
var ny = group.append('path')
.attr('d', NYPath)
.style('fill', 'grey')
.style('stroke', 'black')
.style('stroke-width', 1);
SVG maps made up of paths as it reads. So I go and download the SVG map of NYC and Karnataka. Little did I know SVG maps don’t simply contain paths – they hold all kinds of data about the map in a standard xml document. Time to dig into XML docs and write a parser for ourselves – obviously no one wants to sit and copy paste paths manually. Besides SVG maps tend to have other info like the height and width of the doc which is needed too.
Another request goes to the Google servers. This time I’m interested in this link. I try the code out. Looking up…
I reach here. Further documentation here
The same example code updated would look like this:
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","employee.xml",false);
xmlhttp.send();
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
xmlDoc=xmlhttp.responseXML;
// alert("XML Root Tag Name: " + xmlDoc.documentElement.tagName);
console.log("XML Root Tag Name: " + xmlDoc.documentElement.tagName);
//Using nodeValue and Attributes Properties
//Here both the statement will return you the same result
//Output 001
// alert("Node Value: " + xmlDoc.documentElement.childNodes[1].attributes[0].nodeValue);
console.log("Node Value: " + xmlDoc.documentElement.childNodes[1].attributes[0].nodeValue);
// alert("Node Value: " + xmlDoc.documentElement.childNodes[1].attributes.getNamedItem("id").nodeValue);
console.log("Node Value: " + xmlDoc.documentElement.childNodes[1].attributes.getNamedItem("id").nodeValue);
//Using getElementByTagName Properties
//Here both the statement will return you the same result
//Output 2000
// alert("getElementsByTagName: " + xmlDoc.getElementsByTagName("year")[0].attributes.getNamedItem("id").nodeValue);
console.log("getElementsByTagName: " + xmlDoc.getElementsByTagName("year")[0].attributes.getNamedItem("id").nodeValue);
//Using text Properties
//Output John
// alert("Text Content for Employee Tag: " + xmlDoc.documentElement.childNodes[1].textContent);
console.log("Text Content for Employee Tag: " + xmlDoc.documentElement.childNodes[1].textContent);
}
The svg map of Karnataka has a group of paths drawing the other states
<g id="other_state">
<g id="g67">
<path d="M873.09,2358 ...
</g>
.
.
.
</g>;
Lets try to draw these paths. The d3 code would now look like:
/**
* Code to pare the d attribute form the SVG map of Karnataka
*/
$('#viz-container').html('<button type="button" id="next">Next</button>');
var Districts = [
'Bidar',
'Yadgir',
'Gulbarga',
'Belgaum',
'Bellary',
'Chikballapur',
'Kolar',
'Chikmangaluru',
'Hassan',
'Ramnagara',
'Bangalore Rural',
'Bangalore Urban',
'Mandya',
'Kodagu',
'Tumkur',
'Raichur',
'Koppal',
'Bagalkot',
'Bijapur',
'Dharwad',
'Haveri',
'Gadag',
'DK',
'Mysore',
'Chamrajnagar',
'Shimoga',
'Davangere',
'Chitradurga',
'N Canara',
'Udupi'
];
var tooltip = d3.select("body")
.append("div").attr("id", "pyk-bubble-tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background", "#fff")
.style("padding", "10px 20px")
.style("box-shadow", "0 0 10px #000")
.style("border-radius", "5px")
.text("a simple tooltip");
var svg = d3.select('body').append('svg')
var group = svg.append('g');
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","maps/kmap.svg",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
var h = xmlDoc.getElementsByTagName('svg')[0].getAttribute('height');
var w = xmlDoc.getElementsByTagName('svg')[0].getAttribute('width');
svg.attr('width', w)
.attr('height', h);
var node = xmlDoc.getElementById('ka');
var districtPaths = [];
var nodes = node.getElementsByTagName('path')
for(var i = 0; i < nodes.length; ++i) {
districtPaths[i] = nodes[i].getAttribute('d');
}
console.log(districtPaths);
var ny = group
.selectAll('path')
.data(districtPaths)
.enter()
.append('path')
.attr('d', function (d, i) {
return d;
})
.attr('id', function (d, i){
return i;
})
.style('fill', 'grey')
.style('stroke', 'black')
.style('stroke-width', 1)
.attr('transform', 'scale(0.2)')
.on("mouseover", function (d, i) {
return tooltip.html(Districts[i]).style("visibility", "visible");
})
.on("mousemove", function () {
return tooltip.style("top", (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px");
})
.on("mouseout", function () {
return tooltip.style("visibility", "hidden");
})