From d342e01326bf6de830e4b05b4bdbf26604edf0a0 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 20 Jun 2014 17:54:42 -0400 Subject: [PATCH] Map scale adjusts and displays user-friendly units. --- js/id/ui/scale.js | 60 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/js/id/ui/scale.js b/js/id/ui/scale.js index 36754dfb9..7f165c5c1 100644 --- a/js/id/ui/scale.js +++ b/js/id/ui/scale.js @@ -1,5 +1,7 @@ iD.ui.Scale = function(context) { var projection = context.projection, + imperial = (iD.detect().locale === 'en-us'), + maxLength = 180, tickHeight = 8; // http://stackoverflow.com/a/27943/7620 @@ -15,22 +17,66 @@ iD.ui.Scale = function(context) { var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; // Distance in m return d; + } + + function scaleDefs(loc1, loc2) { + var lat = (loc2[1] + loc1[1]) / 2, + conversion = (imperial ? 3.28084 : 1), + dist = distance(loc1, loc2) * conversion, + scale = { dist: 0, px: 0, text: '' }, + buckets, i, val, dLon; + + if (imperial) { + buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1]; + } else { + buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1]; + } + + // determine a user-friendly endpoint for the scale + for (i = 0; i < buckets.length; i++) { + val = buckets[i]; + if (dist >= val) { + scale.dist = Math.floor(dist / val) * val; + break; + } + } + + dLon = scale.dist / (111132.954 * conversion) / Math.abs(Math.cos( lat * (Math.PI / 180))); + scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]); + + if (imperial) { + if (scale.dist >= 5280) { + scale.dist /= 5280; + scale.text = String(scale.dist) + ' mi'; + } else { + scale.text = String(scale.dist) + ' ft'; + } + } else { + if (scale.dist >= 1000) { + scale.dist /= 1000; + scale.text = String(scale.dist) + ' km'; + } else { + scale.text = String(scale.dist) + ' m'; + } + } + + return scale; }; function update(selection) { - var x = 180, - dims = context.map().dimensions(), + // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn) + var dims = context.map().dimensions(), loc1 = projection.invert([0, dims[1]]), - loc2 = projection.invert([x, dims[1]]), - dist = distance(loc1, loc2); + loc2 = projection.invert([maxLength, dims[1]]), + scale = scaleDefs(loc1, loc2); selection.select('#scalepath') - .attr('d', 'M0.5,0.5v'+ tickHeight +'h' + x + 'v-' + tickHeight); + .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight); selection.select('#scaletext') - .attr('x', x + 5) + .attr('x', scale.px + 8) .attr('y', tickHeight) - .text(String(Math.floor(dist)) + ' m'); + .text(scale.text); }; return function(selection) {