Skip to content

Instantly share code, notes, and snippets.

@mapsense-examples
Last active August 29, 2015 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mapsense-examples/9a63fed6a923aaf9d208 to your computer and use it in GitHub Desktop.
Save mapsense-examples/9a63fed6a923aaf9d208 to your computer and use it in GitHub Desktop.
Drag & drop geojson to map
// Hat tip Mike Bostock: https://github.com/mbostock/polymaps/blob/master/examples/bounds/bounds.js
function bounds(features) {
var i = -1,
n = features.length,
geometry,
bounds = [{lon: Infinity, lat: Infinity}, {lon: -Infinity, lat: -Infinity}];
while (++i < n) {
//geometry = features[i].data.geometry;
geometry = features[i].geometry;
boundGeometry[geometry.type](bounds, geometry.coordinates);
}
return bounds;
}
function boundPoint(bounds, coordinate) {
var x = coordinate[0], y = coordinate[1];
if (x < bounds[0].lon) bounds[0].lon = x;
if (x > bounds[1].lon) bounds[1].lon = x;
if (y < bounds[0].lat) bounds[0].lat = y;
if (y > bounds[1].lat) bounds[1].lat = y;
}
function boundPoints(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoint(bounds, coordinates[i]);
}
function boundMultiPoints(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoints(bounds, coordinates[i]);
}
var boundGeometry = {
Point: boundPoint,
MultiPoint: boundPoints,
LineString: boundPoints,
MultiLineString: boundMultiPoints,
Polygon: function(bounds, coordinates) {
boundPoints(bounds, coordinates[0]); // exterior ring
},
MultiPolygon: function(bounds, coordinates) {
var i = -1, n = coordinates.length;
while (++i < n) boundPoints(bounds, coordinates[i][0]);
}
};
document.addEventListener("DOMContentLoaded", function(event) {
var dropzone = document.querySelector('#myMap');
var dragzone = document.querySelector('#myMap');
var filelist;
dropzone.addEventListener('drop', function(event) {
if (event.preventDefault) {
event.preventDefault();
}
var types = event.dataTransfer.types;
filelist = event.dataTransfer.files;
var file = event.dataTransfer.files[0];
/*if (file.type !== 'application/json') {
alert('Uploaded file must be a compliant JSON file');
return false;
}*/
// Init file reader
var fileReader = new FileReader();
fileReader.onload = function (e) {
processGJ(JSON.parse(fileReader.result));
};
fileReader.onerror = function (e) {
throw 'Error reading JSON file';
};
// Start reading file
fileReader.readAsText(file);
return false;
}, false);
dragzone.addEventListener('dragstart', function(event) {
return true;
}, true);
dragzone.addEventListener('dragend', function(event) {
return true;
}, true);
dropzone.addEventListener('dragenter', function(event) {
if (event.preventDefault) event.preventDefault();
return false;
}, false);
dropzone.addEventListener('dragover', function(event) {
if (event.preventDefault) event.preventDefault(); // allows us to drop
}, false);
dropzone.addEventListener('dragleave', function(event) {
if (event.preventDefault) event.preventDefault(); // allows us to drop
return false;
}, false);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://d3js.org/topojson.v1.min.js" charset="utf-8"></script>
<script src="https://developer.mapsense.co/mapsense.js" charset="utf-8"></script>
<link type="text/css" href="https://developer.mapsense.co/mapsense.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://developer.mapsense.co/stylesheets/bootstrap.min.css" media="screen" type="text/css">
<link rel="stylesheet" href="local.css" media="screen" type="text/css">
<style>
</style>
</head>
<body>
<div id="myMap"></div>
<div class="lede">
<!-- <div class="lede"> -->
<p>Have geojson?
<br/>Drag it onto the map!</p>
<p class="faint">No geojson file handy? <a href="polygons_countries.geojson">Sample here.</a></p>
</div>
<div id="info"></div>
<!-- Modal -->
<div id="fieldModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Pick fields</h4>
</div>
<div id="pickfields" class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">Close</button>
<button type="button" class="btn" id="fields_picked">Map!</button>
</div>
</div>
</div>
</div>
<!-- /Modal -->
<script src='http://code.jquery.com/jquery-1.11.0.min.js' type="text/javascript"></script>
<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js' type="text/javascript"></script>
<script src='dragdrop_geojson.js' type="text/javascript"></script>
<script src='bounds.js' type="text/javascript"></script>
<script>
var my_key = "key-2d5eacd8b924489c8ed5e8418bd883bc";
var home = [{
lon: -130,
lat: 20
}, {
lon: -60,
lat: 55
}];
var map = mapsense.map("#myMap"); //tell it where to go
map.add(
mapsense.basemap()
.apiKey(my_key)
.style("sketch")
)
.extent(home);
var GJ_LAYER;
// Add custom attribution
var attribution = mapsense.attribution('<a target="_blank" href="https://developer.mapsense.co/tileViewer/?tileset=mapsense.earth">©Mapsense ©OpenStreetMap</a>');
attribution.map(map);
// Process GJ
var processGJ = function(GJData) {
GJ_LAYER = mapsense.geoJson()
.features(GJData.features)
.selection(selection_function);
map.add(GJ_LAYER);
//.on("load", zoomBounds)
zoomBounds(GJData);
}
function zoomBounds(e) {
map.extent(bounds(e.features)).zoomBy(-0.1);
}
var tooltip = d3.select('body')
.append("div")
.attr("class", "popup");
function isFloat(n) {
var r = Number(n) && n % 1 !== 0;
return r;
}
var selection_function = (function() {
var whitelist = [];
var id_field = 'gid';
//whitelist = ['population','female','male','hhi','layer','poverty','unemployment','uninsured','postal_code'];
/* The id of the previously hovered-over feature. */
var hoverId = null;
return function(s) {
s.attr("r", function(d) {
return d.properties.radius || 10;
})
.attr("class", function(d) {
var classes = ["mapFeatures"],
props = d.properties;
if (props) {
if (props.layer) classes.push(props.layer);
if (props.sub_layer) classes.push(props.sub_layer);
}
if (d.properties[id_field] !== null && hoverId !== null && d.properties[id_field] == hoverId) {
console.log(d.properties[id_field], hoverId);
classes.push("hoverFeature");
}
return classes.join(' ');
})
.on("mouseover", function(d) {
console.log(d);
//if ( d.properties.minz >= 5 ) {
d3.select(this).classed("selected", true);
//}
var text = "";
var value;
text += '<div class="detailCard"><table><tbody>';
if (whitelist.length > 0) {
for (var i = 0; i < whitelist.length; i++) {
key = whitelist[i];
if (d.properties && d.properties[key]) {
value = d.properties[key];
value = isFloat(value) ? value.toFixed(4) : value;
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + value + '</td></tr>';
}
}
} else {
for (var key in d.properties) {
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + d.properties[key] + '</td></tr>';
}
}
tooltip.html(text);
d3.select('#info').html(text);
if (d.properties[id_field] !== hoverId) {
hoverId = d.properties[id_field];
GJ_LAYER.selection(selection_function);
}
//return tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
//return tooltip.style("top", (d3.event.pageY - 0) + "px").style("left", (d3.event.pageX + 20) + "px");
})
.on("mouseout", function(d) {
d3.select(this).classed("selected", false);
return tooltip.style("visibility", "hidden");
});
};
})();
</script>
</body>
</html>
html, body, #myMap{
height: 100%;
width: 100%;
margin: 0; padding: 0;
font-family: sans-serif;
overflow: hidden;
}
#myMap {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
circle {
fill: rgba(68, 167, 228, 0.5); /*blue*/
stroke: none;
}
.faint { color: #555; }
.top-left {
position: absolute;
top: 5px;
left: 5px;
}
.btn {
background-color: rgba(255,255,255,0.8);
outline: 1px solid rgba(0,0,0,0.3);
min-width: 60px;
padding: 2px 4px;
margin: 2px;
display: inline-block;
}
.csv_point,
circle {
fill: rgba(152, 78, 163, 0.2);
stroke: rgba(152, 78, 163, 1);
stroke-width: 1;
}
.modal-dialog {
width: 400px;
text-align: center;
font-size: 20px;
}
.modal-body {
margin: 0 auto;
text-align: right;
width: 270px;
}
.lede {
position: absolute;
top: 0;
left: 0;
padding: 5px 10px;
background: rgba(255,255,255,0.5);
width: 100%;
}
.mapsense-attribution {
/* adjusted for less contrast */
background-color: rgba(255, 255, 255, 0.5);
color: #777;
position: absolute;
bottom: 0;
right: 0;
font-size: 12px;
font-family: sans-serif;
padding: 2px;
line-height: 1.2em;
text-decoration: none;
user-select: none;
cursor: default;
}
.mapsense-attribution a {
text-decoration: none;
color: #777;
}
.mapsense-attribution a:hover {
text-decoration: none;
color: #444;
}
.hoverFeature {
stroke-width: 2;
}
.popup {
position: absolute;
font-family: sans-serif;
font-size: 11px;
color: #666;
visibility: hidden;
border-radius: 3px;
pointer-events: none;
border: 1px solid #bbb;
padding: 8px;
background-color: rgba(255, 255, 255, .95);
max-height: 500px;
overflow: normal;
}
table {
border-collapse: collapse;
}
table, th, td {
font-size: 12px;
border: 1px solid #ddd;
padding: 1px;
}
.detailKey {
background: #eee;
opacity: .8;
text-transform: uppercase;
font-weight: 600;
}
.detailVal {
background: rgba(255,255,255,0.8);
}
.mapFeatures {
vector-effect: non-scaling-stroke;
stroke-linejoin: round;
stroke-linecap: round;
stroke: orange;
fill: rgba(0,0,0,0);
}
#info {
position: absolute;
bottom: 0px;
right: 0px;
max-width: 300px;
border: 1px solid #ccc;
overflow: scroll;
}
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment