Skip to content

Instantly share code, notes, and snippets.

@hugolpz
Last active December 21, 2015 20:58
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save hugolpz/6364683 to your computer and use it in GitHub Desktop.
India_location_map-en (Wikipedia style + provinces names)

Step 3: Location maps. India's topojson created using makefile.

This code is part of the Wikimaps team push for better wikipedia maps. An efforts for both GIS data collection and map generation for the purpose of encyclopedic cartography and free knowledge.

Meta: v13.08.28. Makefile: Make2/data. Focus: India. Type: location_map.

With: Auto-focus. Wikipedia styles : polygons and conditional boundaries. Download button. Provinces name for fun.

Sources & thanks:

  1. Mike Bostock: Why Use Make

  2. Eidmanna: Austria D3 TopoJSON (makefile in action)

  3. Wikipedia maps' guidelines: Wikipedia:WikiProject_Maps/Conventions

To do: add water bodies.

Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg { border: 5px solid #646464; background-color: #C6ECFF;}
path.L0 { fill:#E0E0E0;}
path.L1 { fill:#FEFEE9;}
path.invisible,text.invisible { fill:none;stroke:none; visibility:none;}
path.L1:hover { fill: #B10000 ;}
.red { border: 5px solid red;} /* Class for tests */
.Topo_50 { border: green; fill:purple; }
.subunit-boundary {
fill: none;
stroke-width:1px;
stroke: #646464;
/* stroke-dasharray: 10,3,3,3; */
stroke-linejoin: round;
}
.international-boundary {
fill: none;
stroke-width:2px;
stroke: #646464;
stroke-dasharray: 16,4,3,4;
stroke-linejoin: round;
}
.place,
.place-label {
fill: #444;
font-size:12px;
}
.coastline {fill: none; stroke:#0978AB;}
text {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
pointer-events: none;
}
.subunit-label {
fill: #777;
fill-opacity: .5;
font-weight: 900;
text-anchor: middle;
font-size: 14px;
}
.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, "item":"India" },
target =WNES.item;
// Function Click > Console
function click(a){ var name = a.properties.name || a.id ; console.log(name);}
// var WNES = { "W": -5.8, "N":51.5, "E": 10, "S": 41.0, "vert_%": 140, "stone":"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 Stoneme 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);
//Pattern injection : disputed-in, disputed-out
var pattern = svg.append("defs")
.append("pattern")
.attr({ id:"hash2_4", width:"6", height:"6", patternUnits:"userSpaceOnUse", patternTransform:"rotate(-45)"})
.append("rect")
.attr({ width:"2", height:"6", transform:"translate(0,0)", fill:"#E0E0E0" });
var pattern = svg.append("defs")
.append("pattern")
.attr({ id:"hash4_2", width:"6", height:"6", patternUnits:"userSpaceOnUse", patternTransform:"rotate(-45)"})
.append("rect")
.attr({ width:"2", height:"6", transform:"translate(0,0)", fill:"#FEFEE9" });
// Path
var path = d3.geo.path()
.projection(projection)
.pointRadius(4);
// Data (getJSON: TopoJSON)
d3.json("./administrative.topo.json", showData);
// ---------- FUNCTION ------------- //
function showData(error, Stone) {
// var #Coord: projection formerly here
// var #Path: formerly here
var countries = topojson.feature(Stone, Stone.objects.admin_0),
subunits = topojson.feature(Stone, Stone.objects.admin_1),
disputed = topojson.feature(Stone, Stone.objects.disputed),
places = topojson.feature(Stone, Stone.objects.places),
neighbors = topojson.neighbors(Stone.objects.admin_1.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);
/* Polygons ********************************************* */
//Append L0 polygons
svg.selectAll(".countries")
.data(countries.features)
.enter().append("path")
.attr("class", "L0")
.attr({fill:"url(#hash4_4);"})
.attr("data-name-en", function(d) { return d.properties.id; })
.attr("d", path)
//.style("fill", function(d, i) { return color(d.color = d3.max(neighbors[i], function(n) { return subunits[n].color; }) + 1 | 0); }) // coloring: fill
.on("click", click);
//Append L1 polygons
svg.selectAll(".subunit")
.data(subunits.features)
.enter().append("path")
.attr("class", function(d){ return d.properties.L0 === target? "L1": "L1 invisible"; } )
.attr("data-name-en", function(d) { return d.id; })
.attr("d", path )
//.style("fill", function(d, i) { return color(d.color = d3.max(neighbors[i], function(n) { return subunits[n].color; }) + 1 | 0); }) // coloring: fill
.on("click", click);
//Append disputed polygons
svg.selectAll(".disputed")
.data(disputed.features)
.enter().append("path")
.attr("class", function(d){ return d.properties.L0 === target? "disputed in": "disputed out"; } )
.attr("fill", function(d){ return d.properties.L0 === target? "url(#hash2_4)": "url(#hash4_2)"} )
.attr("data-name-en", function(d) { return d.id; })
.attr("d", path )
//.style("fill", function(d, i) { return color(d.color = d3.max(neighbors[i], function(n) { return subunits[n].color; }) + 1 | 0); }) // coloring: fill
.on("click", click);
/* Arcs ************************************************* */
// Admin1-borders filtered
svg.append("path")
.datum(topojson.mesh(Stone, Stone.objects.admin_1, function(a,b) { return a !==b && a.properties.L0 === b.properties.L0 && a.properties.L0 === target ;}))
.attr("d", path)
.attr("class", "subunit-boundary");
// Admin0-borders filtered
svg.append("path")
.datum(topojson.mesh(Stone, Stone.objects.admin_0, function(a,b) { return a!==b;}))
.attr("d", path)
.attr("class", "international-boundary");
// Coast-borders filtered
svg.append("path")
.datum(topojson.mesh(Stone, Stone.objects.admin_0, function(a,b) { return a===b;}))
.attr("d", path)
.attr("class", "coastline");
/* DOT & LABELS ******************************************* */
// Places: dot placement ********************************** */
svg.append("path")
.datum(places)
.attr("d", path)
.attr("class", "place");
// Places label placement
svg.selectAll(".place-label")
.data(places.features)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.attr("dy", ".35em")
.text( function(d) { return d.id;} )
.attr("x", function(d) { return d.geometry.coordinates[0] > -1 ? 6 : -6; })
.style("text-anchor", function(d) { return d.geometry.coordinates[0] > -1 ? "start" : "end"; });
/* L1 labels ******************************************** */
svg.selectAll(".subunit-label")
.data(subunits.features)
.enter().append("text")
.attr("class", function(d){ return d.properties.L0 === target? "subunit-label": "subunit-label invisible"; } )
.attr("data-name-en", function(d) { return d.properties.id ;})
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
// Vertical adjustment custom:
.attr("dy", function(d){
if(d.id==="Delhi"|| d.id==="2nd capital" ){return ".5em"}
else{return ".2em"}}) // default
// Vertical adjustment custom:
.attr("font-size", function(d){
if(d.id==="Delhi"|| d.id==="2nd capital" ){return "1.2"}
else{return "6px"} }) // default
.text(function(d) { return d.id; });
}
</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://raw.github.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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment