Skip to content

Instantly share code, notes, and snippets.

@punkish
Created May 4, 2012 16:22
Show Gist options
  • Save punkish/2595879 to your computer and use it in GitHub Desktop.
Save punkish/2595879 to your computer and use it in GitHub Desktop.
elevation profile
<!doctype html>
<head>
<meta charset="utf-8">
<style type="text/css">
body {
position: relative;
height: 100%;
}
header {
font-family: serif;
font-size: 3em;
}
#main {
position: relative;
width: 960px;
left: 40px;
margin: 0 auto;
border: 0px solid red;
height: 700px;
}
.chart div {
font: 10px sans-serif;
background-color: steelblue;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
footer {
position: relative;
bottom: 0px;
}
#map {
border: 1px solid grey;
/*
width: 700px;
height: 300px;
*/
}
#viz {
border: 1px solid grey;
}
path.line {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
.xaxis {
fill: none;
stroke: #000;
stroke-width: 1px;
shape-rendering: crispEdges;
}
path.area {
fill: #e7e7e7;
}
.axis {
shape-rendering: crispEdges;
}
.x.axis line {
stroke: #fff;
}
.x.axis .minor {
stroke-opacity: .5;
}
.x.axis path {
display: none;
}
.y.axis line, .y.axis path {
fill: none;
stroke: #000;
}
circle.merc {
fill:#005982;
}
circle.elev {
fill:#ff0000;
}
path.connect {
fill:none;
stroke-width:0.2;
stroke:#aaa;
}
text {
font-family: Arial;
font-size: 9pt;
}
.chart {
background-color: #fff;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="viz"></div>
<script src="http://mbostock.github.com/d3/d3.v2.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
var d3_chart = function() {
var arr_x = [],
arr_y = [],
title = "",
div = "",
dims = {
container: { width: 0, height: 0 },
padding: { left: 50, top: 20, right: 20, bottom: 30 },
plot: { width: 0, height: 0 },
title: { left: 10, top: 0 }
},
drawbins = "no";
// generate chart here, using `width` and `height`
function my() {
dims.plot.width = dims.container.width - (dims.padding.left + dims.padding.right);
dims.plot.height = dims.container.height - (dims.padding.top + dims.padding.bottom);
dims.title.top = dims.plot.height - 20;
var ymin = d3.min(arr_y),
ymax = d3.max(arr_y),
x = d3.scale.linear().domain([0, arr_x.length]).range([0, dims.plot.width]),
y = d3.scale.linear().domain(d3.extent(arr_y)).range([dims.plot.height, 0]),
xAxis = d3.svg.axis().scale(x).tickSize(-dims.plot.height).tickSubdivide(true),
yAxis = d3.svg.axis().scale(y).ticks(4).orient("left");
// A line generator, for the dark stroke.
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d, i) { return x(i); })
.y(function(d) { return y(d); });
// Adjustment for negative values. This is what allows making a
// nice looking profile if there are negative values in height.
var adjusted_height = dims.plot.height;
if (ymin < 0) {
adjusted_height = dims.plot.height - Math.abs(dims.plot.height * ymin / (ymax - ymin));
}
// An area generator, for the light fill.
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d, i) { return x(i); })
.y0(adjusted_height)
.y1(function(d) { return y(d); });
// Add an SVG element with the desired dimensions and margin.
$("#" + div)
.css("width", dims.container.width)
.css("height", dims.container.height)
.empty();
var svg = d3.select("#" + div)
.append("svg:svg")
.attr("width", dims.plot.width + dims.padding.left + dims.padding.right)
.attr("height", dims.plot.height + dims.padding.top + dims.padding.bottom)
.append("svg:g")
.attr("transform", "translate(" + dims.padding.left + "," + dims.padding.top + ")");
// Add the clip path.
svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", dims.plot.width)
.attr("height", dims.plot.height);
// Add the area path.
svg.append("svg:path")
.attr("class", "area")
.attr("clip-path", "url(#clip)")
.attr("d", area(arr_y));
// Add the x-axis.
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + adjusted_height + ")")
.call(xAxis);
// Add the line path.
svg.append("svg:path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr("d", line(arr_y));
svg.append("line")
.attr("x1", 0)
.attr("y1", adjusted_height)
.attr("x2", dims.plot.width)
.attr("y2", adjusted_height)
.attr("class", "xaxis");
svg.selectAll("circle.elev")
.data(arr_y)
.enter().append('svg:circle')
.attr('class', 'elev')
.attr('r', 2)
.attr('cx', function(d, i) {
return x(i);
})
.attr('cy', function(d, i) {
return y(d)
})
.on("mouseover", function() {
d3.select(this).attr('r', 5);
})
.on("mouseout", function() {
d3.select(this).attr('r', 2);
})
// Add the y-axis.
svg.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(0, 0)")
.call(yAxis);
// Add a small label for the symbol name.
svg.append("svg:text")
.attr("x", dims.title.left)
.attr("y", dims.title.top)
.attr("text-anchor", "start")
.text(title);
// Add a legend.
svg.append("svg:text")
.attr("x", dims.title.left)
.attr("y", 20)
.attr("text-anchor", "start")
.text("max: " + ymax);
svg.append("svg:text")
.attr("x", dims.title.left)
.attr("y", 35)
.attr("text-anchor", "start")
.text("min: " + ymin);
if (drawbins == "yes") {
var intervals = [
["Cm", 542, 488.3, "#7FA056"],
["O", 488.3, 443.7, "#009270"],
["S", 443.7, 416, "#B3E1B6"],
["D", 416, 359.2, "#CB8C37"],
["C", 359.2, 299, "#67A599"],
["P", 299, 251, "#F04028"],
["Tr", 251, 199.6, "#812B92"],
["J", 199.6, 145.5, "#34B2C9"],
["K", 145.5, 65.5, "#7FC64E"],
["Pg", 65.5, 23.03, "#FD9A52"],
["Ng", 23.03, 2.588, "#FFE619"],
["Q", 2.588, 0, "#F9F97F"]
];
var x = d3.scale.linear()
.domain([542, 0])
.range([0, dims.plot.width]),
y = dims.plot.height,
height = 20;
svg.selectAll(".rect")
.data(intervals)
.enter().append("rect")
.attr("x", function(d) { return x(d[1]); })
.attr("y", y)
.attr("width", function(d) { return (x(d[2]) - x(d[1])); })
.attr("height", 20)
.attr("fill", function(d) { return d[3]; })
.style("stroke", "#000000");
svg.selectAll(".intervalLabel")
.data(intervals)
.enter().append("text")
.attr("class", "intervalLabel")
.attr("text-anchor", "middle")
.attr("x", function(d) { return x((d[1] + d[2]) / 2); })
.attr("y", y + (height / 2) + 5)
.text(function(d) { return ((d[1] - d[2]) > 20 ? d[0] : ""); });
}
}
my.width = function(value) {
if (!arguments.length) return dims.container.width;
dims.container.width = value;
return my;
};
my.height = function(value) {
if (!arguments.length) return dims.container.height;
dims.container.height = value;
return my;
};
my.arr_x = function(value) {
if (!arguments.length) return arr_x;
arr_x = value;
return my;
};
my.arr_y = function(value) {
if (!arguments.length) return arr_y;
arr_y = value;
return my;
};
my.div = function(value) {
if (!arguments.length) return div;
div = value;
return my;
};
my.title = function(value) {
if (!arguments.length) return title;
title = value;
return my;
};
my.drawbins = function(value) {
if (!arguments.length) return title;
drawbins = value;
return my;
};
return my;
};
var d3_map = function() {
var arr_x = [],
arr_y = [],
dims = {
container: { width: 0, height: 0 },
padding: { left: 50, top: 20, right: 20, bottom: 30 },
plot: { width: 0, height: 0 },
title: { left: 10, top: 0 }
};
// generate chart here, using `width` and `height`
function my() {
dims.plot.width = dims.container.width - (dims.padding.left + dims.padding.right);
dims.plot.height = dims.container.height - (dims.padding.top + dims.padding.bottom);
dims.title.top = dims.plot.height - 20;
// Add an SVG element with the desired dimensions and margin.
$("#" + div)
.css("width", dims.container.width)
.css("height", dims.container.height)
.empty();
var svg = d3.select("#" + div)
.append("svg:svg")
.attr("width", dims.plot.width + dims.padding.left + dims.padding.right)
.attr("height", dims.plot.height + dims.padding.top + dims.padding.bottom);
var merc = d3.geo.mercator()
.scale(700)
.translate([350, 150]);
svg.selectAll("circle.merc")
.data(arr_x)
.enter().append('svg:circle')
.attr('class', 'merc')
.attr('r', 1)
.attr('transform', function(d) {
return 'translate(' + merc(d).join(',') + ')';
});
}
my.width = function(value) {
if (!arguments.length) return dims.container.width;
dims.container.width = value;
return my;
};
my.height = function(value) {
if (!arguments.length) return dims.container.height;
dims.container.height = value;
return my;
};
my.arr_x = function(value) {
if (!arguments.length) return arr_x;
arr_x = value;
return my;
};
my.arr_y = function(value) {
if (!arguments.length) return arr_y;
arr_y = value;
return my;
};
my.div = function(value) {
if (!arguments.length) return div;
div = value;
return my;
};
my.title = function(value) {
if (!arguments.length) return title;
title = value;
return my;
};
return my;
};
var data = {
"elevation" : [
{ "pt" : [ -121.181, 38.682 ], "ht" : 52 },
{ "pt" : [ -120.742, 39.082 ], "ht" : 1245 },
{ "pt" : [ -120.303, 39.482 ], "ht" : 2063 },
{ "pt" : [ -119.863, 39.881 ], "ht" : 1507 },
{ "pt" : [ -119.424, 40.281 ], "ht" : 1565 },
{ "pt" : [ -118.984, 40.681 ], "ht" : 1436 },
{ "pt" : [ -118.545, 41.08 ], "ht" : 1594 },
{ "pt" : [ -118.105, 41.48 ], "ht" : 1254 },
{ "pt" : [ -117.666, 41.88 ], "ht" : 1409 },
{ "pt" : [ -117.226, 42.28 ], "ht" : 1603 },
{ "pt" : [ -116.787, 42.679 ], "ht" : 2016 },
{ "pt" : [ -116.216, 42.791 ], "ht" : 1115 },
{ "pt" : [ -115.644, 42.902 ], "ht" : 852 },
{ "pt" : [ -115.073, 43.014 ], "ht" : 917 },
{ "pt" : [ -114.502, 43.125 ], "ht" : 1415 },
{ "pt" : [ -113.93, 43.236 ], "ht" : 1443 },
{ "pt" : [ -113.359, 43.348 ], "ht" : 1609 },
{ "pt" : [ -112.788, 43.459 ], "ht" : 1540 },
{ "pt" : [ -112.217, 43.571 ], "ht" : 1541 },
{ "pt" : [ -111.645, 43.682 ], "ht" : 1797 },
{ "pt" : [ -111.074, 43.794 ], "ht" : 1927 },
{ "pt" : [ -110.503, 43.905 ], "ht" : 2102 },
{ "pt" : [ -109.931, 44.016 ], "ht" : 3414 },
{ "pt" : [ -109.36, 44.128 ], "ht" : 2797 },
{ "pt" : [ -108.789, 44.239 ], "ht" : 1722 },
{ "pt" : [ -108.218, 44.351 ], "ht" : 1316 },
{ "pt" : [ -107.646, 44.462 ], "ht" : 1914 },
{ "pt" : [ -107.056, 44.317 ], "ht" : 2967 },
{ "pt" : [ -106.465, 44.173 ], "ht" : 1313 },
{ "pt" : [ -105.874, 44.028 ], "ht" : 1421 },
{ "pt" : [ -105.284, 43.883 ], "ht" : 1441 },
{ "pt" : [ -104.693, 43.738 ], "ht" : 1305 },
{ "pt" : [ -104.103, 43.594 ], "ht" : 1189 },
{ "pt" : [ -103.512, 43.449 ], "ht" : 1112 },
{ "pt" : [ -102.921, 43.304 ], "ht" : 919 },
{ "pt" : [ -102.331, 43.16 ], "ht" : 1040 },
{ "pt" : [ -101.74, 43.015 ], "ht" : 1014 },
{ "pt" : [ -101.149, 42.87 ], "ht" : 941 },
{ "pt" : [ -100.559, 42.725 ], "ht" : 865 },
{ "pt" : [ -99.968, 42.581 ], "ht" : 782 },
{ "pt" : [ -99.378, 42.436 ], "ht" : 746 },
{ "pt" : [ -98.787, 42.291 ], "ht" : 670 },
{ "pt" : [ -98.196, 42.146 ], "ht" : 557 },
{ "pt" : [ -97.606, 42.002 ], "ht" : 485 },
{ "pt" : [ -97.015, 41.857 ], "ht" : 510 },
{ "pt" : [ -96.424, 41.712 ], "ht" : 404 },
{ "pt" : [ -95.834, 41.567 ], "ht" : 304 },
{ "pt" : [ -95.243, 41.423 ], "ht" : 400 },
{ "pt" : [ -94.653, 41.278 ], "ht" : 390 },
{ "pt" : [ -94.062, 41.133 ], "ht" : 381 },
{ "pt" : [ -93.471, 40.989 ], "ht" : 302 },
{ "pt" : [ -92.881, 40.844 ], "ht" : 287 }
]
};
var arr_x = [], arr_y = [], ymin = 0, ymax = 0;
for (var i = 0, len = data.elevation.length; i < len; i++) {
arr_x.push(data.elevation[i].pt);
arr_y.push(data.elevation[i].ht);
}
d3_chart()
.div("viz")
.title("profile")
.width(700)
.height(200)
.arr_x(arr_x)
.arr_y(arr_y)
.drawbins("no")();
d3_map()
.div("map")
.width(700)
.height(300)
.arr_x(arr_x)
.arr_y(arr_y)();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment