2020: javascript

Craters

micro.blog Craters on the move

Topographic Contours

Drawing Contour Lines using d3 topojson

  • Handy list of Munros here
  • Get your GeoJSON from Andy Woodruff
  • Command line GeoJSON > TopoJSON using geo2topo
  • Remove any "arcs" data from topo.json file of the elevations you don't want to show - can be laborious - especially if your bounding box is too large

Based on: Contours of Nepal using topojson and d3.js

Look at the Source Code of the maps, but reference the D3 topojson in your header:

<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://d3js.org/topojson.v1.min.js"></script>

Footer

<script type="text/javascript">
var h = 500,
w = 960;

// set-up unit projection and path
var projection = d3.geo.mercator()
.scale(1)
.translate([0, 0]);

var path = d3.geo.path()
.projection(projection);

// set-up svg canvas
var svg = d3.select("#map")
.append("svg")
.attr("height", h)
.attr("width", w);

// set-up scale for colour coding contours
var cScale = d3.scale.linear()
.domain([0, 1]);

// read in your topojson mine are referred to as ben
d3.json("/topo.json", function(error, ben) {

// first variable is used to centre and scale map to viewport
// could have used the bbox feature (see https://github.com/mbostock/topojson/issues/67) 
var bTopo = topojson.feature(ben, ben.objects.countours),
    topo = bTopo.features;

// calculate range for colours based on elevation property 
// Note when converting to topojon the default is to REMOVE all properties from the input file, you need to use the -p switch.
var hRange = d3.extent(topo, function(d, i) {
    return d.properties.elevation
});

cScale.domain(hRange);

// calculate bounds, scale and transform 
// see http://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object
var b = path.bounds(bTopo),
    s = .95 / Math.max((b[1][0] - b[0][0]) / w, (b[1][1] - b[0][1]) / h),
    t = [(w - s * (b[1][0] + b[0][0])) / 2, (h - s * (b[1][1] + b[0][1])) / 2];

projection.scale(s)
    .translate(t);

svg.selectAll("path")
    .data(topo).enter()
    .append("path")
    .style("fill", "none")
    .style("stroke", function(d, i) {
        return interp(cScale(d.properties.elevation));
    })
    .attr("d", path)
    .on("mouseover", highlight) // just a little example of what's available in terms of interaction
    .on("mouseout", function (d,i) {unhighlight(this,d); 
    });
});

// function to interpolate between to colours
// see http://stackoverflow.com/questions/12217121/continuous-color-scale-from-discrete-domain-of-strings
function interp(x) {
    var ans = d3.interpolateLab("#9aff42", "#ffd14a")(x);
return ans
}

// A simple highlight example
function highlight(x) {
    var s = d3.select(this);
    s.style("stroke", "blue");
}
// function highlight(x) {
//    var s = d3.select(this);
//    s.attr("d", "([path) => tooltip.show(path)");
// }
function unhighlight(x,y) {
    var old = y.properties.elevation;
    var u = d3.select(x);
    u.style("stroke", function(d, i) {
        return interp(cScale(old));
    })
}

</script>

The Munros drawn so far: