|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
svg { |
|
border: 3px solid #646464; |
|
background-color: #C6ECFF; |
|
} |
|
* { |
|
fill-opacity: 0.3; |
|
stroke-opacity: 0.3; |
|
} |
|
.polygon, .lineString, .point { |
|
stroke-width: 1px; |
|
stroke: #0978AB;; |
|
stroke-linejoin: round ; |
|
} |
|
.polygon, .point { |
|
fill:#C6ECFF; |
|
} |
|
.lineString { |
|
fill: none; |
|
} |
|
.L1 { fill: #FFFFFF;} |
|
.data:hover { stroke: #B10000; stroke-width: 2px; fill-opacity: 1; stroke-opacity: 0.7; } |
|
.datum:hover { stroke: #00B100; stroke-width: 2px; fill-opacity: 1; stroke-opacity: 0.7; } |
|
|
|
/*.subunit-boundary { |
|
fill: none; |
|
stroke-linejoin: round; |
|
} */ |
|
.international-boundary { |
|
stroke-width:3px; |
|
stroke-dasharray: 16,4,3,4; |
|
} |
|
|
|
.legend { |
|
font-size: 16px; |
|
font-weight: bold; |
|
text-anchor: start; |
|
} |
|
.download { |
|
background: #333; |
|
color: #FFF; |
|
font-weight: 900; |
|
border: 2px solid #B10000; |
|
padding: 4px; |
|
margin:4px; |
|
} |
|
</style> |
|
<body> |
|
<script src="http://code.jquery.com/jquery-2.0.2.min.js"></script> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<script> |
|
// 1. -------------- SETTINGS ------------- // |
|
// India geo-frame borders in decimal ⁰ |
|
var WNES = { "W": 67.0, "N":37.5, "E": 99.0, "S": 5.0, "vert_%": 106, "jsond":"India" }; |
|
// var WNES = { "W": -5.8, "N":51.5, "E": 10, "S": 41.0, "vert_%": 140, "jsond":"France" }; |
|
|
|
// Geo values of interest : |
|
var latCenter = (WNES.S + WNES.N)/2, |
|
lonCenter = (WNES.W + WNES.E)/2, |
|
geo_width = (WNES.E - WNES.W), |
|
geo_height= (WNES.N - WNES.S); |
|
// HTML expected jsondme dimensions |
|
var width = 600, |
|
height = width * (geo_height / geo_width); |
|
|
|
// var color = d3.scale.category10(); // d3.scale.ordinal().domain(["000000", "FFFFFF", "baz"]).range(colorbrewer.RdBu[9]); |
|
|
|
|
|
// Projection: projection, reset scale and translate |
|
var projection = d3.geo.equirectangular() |
|
.scale(1) |
|
.translate([0, 0]); |
|
|
|
// SVG injection: |
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
svg.append("rect") |
|
.attr("id", "background") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.attr("fill", "#C6ECFF") |
|
.attr("fill-opacity", 0.2); |
|
|
|
// Path |
|
var path = d3.geo.path() |
|
.projection(projection) |
|
.pointRadius(4); |
|
|
|
|
|
// Data (getJSON: TopoJSON) |
|
d3.json("final_adms_India.json", showData); |
|
|
|
// .json contain features layers : countries, subunits, places. Each shape have an attibute `name`. |
|
|
|
// ---------- FUNCTION ------------- // |
|
function showData(error, jsond) { |
|
|
|
// var #Coord: projection formerly here |
|
|
|
// var #Path: formerly here |
|
var countries = topojson.feature(jsond, jsond.objects.countries), |
|
subunits = topojson.feature(jsond, jsond.objects.subunits), |
|
places = topojson.feature(jsond, jsond.objects.places), |
|
neighbors = topojson.neighbors(jsond.objects.subunits.geometries); // coloring: full line |
|
|
|
// Focus area box compute for derive scale & translate. |
|
// [[left, bottom], [right, top]] // E W N S |
|
var b = path.bounds(countries), |
|
s = 1 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height), |
|
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2]; |
|
|
|
// Projection update |
|
projection = projection |
|
.scale(s) |
|
.translate(t); |
|
|
|
var grp1 = svg.append("g") |
|
.attr("class", "polygon") |
|
.on("click", click); |
|
|
|
var grp2 = svg.append("g") |
|
.attr("class", "lineString"); |
|
|
|
var grp3 = svg.append("g") |
|
.attr("class", "point") |
|
.on("click", click); |
|
|
|
/** ******************* POLYGONS & .FEATURE() ******************** /**/ |
|
//Append L0 polygons |
|
grp1.append("path") //datum |
|
.datum(countries) |
|
.attr("class", "datum L0") // for fun and svg code readability: |
|
.attr("d", path); |
|
|
|
grp1.selectAll(".polygons") //data |
|
.data(topojson.feature(jsond, jsond.objects.countries).features) |
|
.enter().append("path") |
|
.attr("class", "data L0") // for fun and svg code readability: |
|
.attr("data-name-en", function(d) { return d.properties.name; }) //for fun and svg code readability |
|
.attr("d", path); |
|
|
|
//Append L1 polygons |
|
grp1.append("path") |
|
.datum(topojson.feature(jsond, jsond.objects.subunits)) |
|
.attr("class", "datum L1") // for fun and svg code readability |
|
.attr("d", path); |
|
|
|
grp1.selectAll(".polygons") |
|
.data(topojson.feature(jsond, jsond.objects.subunits).features) |
|
.enter().append("path") |
|
.attr("class", "data L1") // for fun and svg code readability: |
|
.attr("data-name-en", function(d) { return d.properties.name; }) // for fun and svg code readability: |
|
.attr("d", path); |
|
|
|
|
|
/** ******************* LINESTRING & .MESH() ******************** /**/ |
|
// DATUM : LineString: Conditional Border |
|
grp2.append("path") |
|
.datum(topojson.mesh(jsond, jsond.objects.subunits, function(a,b) { if (a.properties.name!==b.properties.name){var ret = a;}return ret;})) |
|
.attr("class", "datum subunit-boundary") |
|
.attr("d", path); |
|
|
|
// DATA > LineSTRING: Conditional Border ? HOW TO DO THIS WITH DATA () |
|
grp2.append("path") |
|
.datum(topojson.mesh(jsond, jsond.objects.countries, function(a,b) { if (a.properties.name!==b.properties.name){var ret = a;}return ret;})) |
|
.attr("class", "datum international-boundary") |
|
.attr("d", path); |
|
|
|
/** ******************* POINTS ******************** /**/ |
|
//* DATUM > POINTS: |
|
grp3.append("path") |
|
.datum(topojson.feature(jsond, jsond.objects.places)) |
|
.attr("class", "datum points") // for fun and svg code readability |
|
.attr("d", path); /**/ |
|
|
|
/** ******************* SUGAR ******************** /**/ |
|
function click(a){ console.log(a.properties.name);} |
|
|
|
// Toggle function here |
|
var leg = svg.append("g") |
|
.attr("groupmode","layer") |
|
.attr("class", "legend") |
|
.attr({'id':'Legend','label':'Legend'}); |
|
|
|
leg.append("text") |
|
.attr("x", 20) |
|
.attr("y", height - 20) |
|
.style("fill", "#B10000") |
|
.on("click", function(){ |
|
console.log('1: click'); |
|
// Determine if current line is visible |
|
var newOpacity = data.active ? 1 : 0; |
|
// Hide or show the elements |
|
d3.select(".data").style("opacity", newOpacity); |
|
// Toggle elements's active s |
|
data.active = !data.active; |
|
}) |
|
.text(".data()"); |
|
|
|
leg.append("text") |
|
.attr("x", 20) |
|
.attr("y", height - 40) |
|
.style("fill", "#00B100") |
|
.on("click", function(){ |
|
console.log('1: click'); |
|
// Determine if current line is visible |
|
var newOpacity = datum.active ? 1 : 0; |
|
// Hide or show the elements |
|
d3.select(".datum").style("opacity", newOpacity); |
|
// Toggle elements's active s |
|
datum.active = !datum.active; |
|
}) |
|
.text(".datum()"); |
|
|
|
} |
|
</script> |
|
<br /> |
|
<div> |
|
<a class="download ac-icon-download" href="javascript:javascript: (function () { var e = document.createElement('script'); if (window.location.protocol === 'https:') { e.setAttribute('src', 'https://rawgithub.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js'); } else { e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js'); } e.setAttribute('class', 'svg-crowbar'); document.body.appendChild(e); })();"><!--⤋--><big>⇩</big> Download</a> -- Works on Chrome. Feedback welcome for others web browsers. |
|
</div> |
|
<br /> |
|
</body> |
|
</html> |
Nice reference, Hugo
I think you have these signatures flipped; data accepts a key parameter, datum does not.
.datum([values[, key]])
.data([value]) :