Skip to content

Instantly share code, notes, and snippets.

@jhnklly
Last active August 29, 2015 14:23
Show Gist options
  • Save jhnklly/3ae6800eb8897fd2e359 to your computer and use it in GitHub Desktop.
Save jhnklly/3ae6800eb8897fd2e359 to your computer and use it in GitHub Desktop.
osm2
html, body, #myMap {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
font: 11px 'Droid Sans', sans-serif;
color: #666;
}
* { box-sizing: border-box }
.ms {
stroke-width: 1;
stroke: #ccc;
stroke-opacity: 0.8;
fill-opacity: 0.5;
mix-blend-mode: multiply;
/*
*/
}
circle {
vector-effect: non-scaling-stroke;
}
.A {
stroke: cyan;
fill: cyan;
/*
stroke-width: 0;
*/
}
.B {
stroke: magenta;
fill: magenta;
/*
stroke-width: 0;
*/
}
a.button {
display: inline-block;
padding: 5px 10px;
border: 2px solid #777;
font: 16px bold 'Droid Sans', sans-serif;
line-height: 37px;
color: #777;
height: 50px;
min-width: 50px;
vertical-align: top;
margin-left: 4px;
text-align: center;
cursor: pointer;
}
a.button:hover {
border: 2px solid #000;
color: #000;
}
input {
border: 0s;
font: 16px 'Droid Sans', sans-serif;
}
input:focus {
outline-offset: 0px;
}
#refresh { margin-top: 5px;}
#selector_a {
outline: 13px solid rgba(0,255,255,0.6);
mix-blend-mode: multiply;
margin: 13px;
}
#selector_b {
outline: 13px solid rgba(255,0,255,0.6);
mix-blend-mode: multiply;
margin: 13px;
margin-left: 0px;
}
#ui {
position: absolute;
z-index: 99;
margin: 0;
top: 0;
left: 0;
clear: both;
}
#selector {
font: 20px 'Droid Sans', sans-serif;
}
#legend {
background: rgba(255,255,255,0.8);
overflow: auto;
display: inline-block;
}
#color-chips, #color-values {
float: left;
margin-left: 5px;
}
#color-values{
white-space: pre;
padding-right: 5px;
}
#color-values textarea {
overflow:hidden;
margin: 0;
border: none;
resize: none;
height: 100%;
}
.mouseinfo {
position: absolute;
bottom: 0;
left: 0;
pointer-events: none;
max-width: 300px;
/*font: 20px 'Droid Sans', sans-serif;*/
}
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ddd;
padding: 0 2px;
}
.detailKey {
background: #eee;
opacity: .8;
text-transform: uppercase;
font-weight: 600;
}
.detailVal {
background: rgba(255,255,255,0.8);
}
<!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 type="text/css" href="index.css" rel="stylesheet"/>
<style>
circle {
vector-effect: non-scaling-stroke;
/*We leave them unpainted until they match a regex later*/
stroke: none;
fill: none;
}
</style>
</head>
<body>
<div id="myMap"></div>
<div id="ui">
<div id="control"></div>
<div id="legend">
</div>
</div>
<script>
function getBody() {
var doc, body, iframe, src;
body = d3.select('body');
if (d3.select('iframe').node()) {
iframe = d3.select('iframe').node();
src = d3.select(iframe).attr('src');
if (src.slice(0,22) == '/mapsense-examples/raw') {
doc = iframe.contentDocument || iframe.contentWindow.document;
body = d3.select(doc).select('body');
}
}
return body;
}
function readUrl() {
var body = getBody();
var hash = location.hash.substring(1).split('/');
console.log(hash, d3.select(body).node().select('#selector_a').node().value );
d3.select(body).node().select('#selector_a').node().value = hash[0] || G.input_A;
d3.select(body).node().select('#selector_b').node().value = hash[1] || G.input_B;
}
function writeUrl() {
var body = getBody();
var new_hash = '#' + d3.select(body).node().select('#selector_a').node().value +
'/' + d3.select(body).node().select('#selector_b').node().value;
window.location.hash = new_hash;
}
var G = {}; // A global object to store variables
G.key = 'key-2d5eacd8b924489c8ed5e8418bd883bc';
G.simplify = '&ringSpan=10&lineSpan=10&s=10';
G.home = [ // we'll set the map extent to these bounds
{lon: -125, lat: -60},
{lon: 160, lat: 75}
];
G.basemap = 'sketch';
G.input_A = 'kitten';
G.input_B = 'puppy';
G.samples = [
['kitten','puppy'],
['bar','pub'],
['soda','pop'],
['cafe','caffe'],
['church','mosque'],
['ice cream','gelato'],
['Martin Luther King','Jefferson Davis'],
['bicycle','motorcycle'],
['east','west']
];
G.samples_i = 0;
G.layers = {
'base': { 'url': '', 'default': false},
'overlay_a': {
'url': 'https://{S}-api.mapsense.co/universes/mapsense.planet_osm_points/{Z}/{X}/{Y}.topojson?api-key=' + G.key,
'where': "&where=name=='"+G.input_A+"'",
'params': '&density=200',
'class': 'A',
'default': true
},
'overlay_b': {
'url': 'https://{S}-api.mapsense.co/universes/mapsense.planet_osm_points/{Z}/{X}/{Y}.topojson?api-key=' + G.key,
'where': "&where=name=='"+G.input_B+"'",
'params': '&density=200',
'class': 'B',
'default': true
},
'labels': { 'url': '', 'default': false}
};
G.selector_options = ['place_of_worship','school','bench','restaurant','fast_food','cafe','bicycle_parking','pub','bar','swimming_pool','university','college'];
G.selector_options.sort();
initSelect(); // initialize the selector UI
//readUrl();
initMap(); // initialize the map
// Add a div to display info mouseover info
var mouseinfo = d3.select('body')
.append("div")
.attr("class","mouseinfo");
function initMap() {
var param_selection_function = (function(show_list) {
return function(s) {
s.attr("r", 3);
s.attr("class", function(f){
var classes = ['ms'];
classes.push(G.layers['overlay_a']['class']);
//var show_list = ['amenity','tourism','name'];
var show_list = ['name'];
for (var i = 0; i < show_list.length; i++) {
if (f.properties && f.properties[show_list[i]]) {
classes.push(f.properties[show_list[i]]);
var feature_value = f.properties[show_list[i]];
var A_value = d3.select('#selector_a').node().value;
var B_value = d3.select('#selector_b').node().value;
var A_regex = new RegExp(escapeRegExp(A_value), "gi");
var B_regex = new RegExp(escapeRegExp(B_value), "gi");
// at this point, the line above is the same as: var regex = /#abc#/g;
if ( A_regex.test(feature_value) ) {
classes.push('A');
} else if ( B_regex.test(feature_value) ) {
classes.push('B');
}
}
};
return classes.join(' ');
})
s.on("mouseover", function(d) { // Bind a function to mouseover
// This will build a table to display the field names and values
var text = "";
var value;
var no_list = ['DND_UUID'];
text += '<div class="detailCard"><table><tbody>';
if (show_list.length > 0) { // if there's a show_list, only show those fields
for (var i = 0; i < show_list.length; i++) {
key = show_list[i];
if (d.properties && d.properties[key]) {
value = d.properties[key];
value = formatValue(value);
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + value + '</td></tr>';
}
}
} else { // if no show_list, show all fields
for (var key in d.properties) {
// except if it's in the no_list
if ( no_list.indexOf(key.toUpperCase()) == -1 ) {
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + d.properties[key] + '</td></tr>';
}
}
}
mouseinfo.html(text); // Update the mouseinfo div with the dynamic info
G.layers['overlay_a'].ms_layer.selection(param_selection_function([]));
});
};
});
var param_selection_function_b = (function(show_list) {
return function(b) {
b.attr("r", 3);
console.log('psfb');
console.log(b);
b.attr("class", "B");
b.attr("class", function(f){
console.log(f);
var classes = ['ms'];
classes.push(G.layers['overlay_b']['class']);
//var show_list = ['amenity','tourism','name'];
var show_list = ['name'];
for (var i = 0; i < show_list.length; i++) {
if (f.properties && f.properties[show_list[i]]) {
classes.push(f.properties[show_list[i]]);
var feature_value = f.properties[show_list[i]];
var A_value = d3.select('#selector_a').node().value;
var B_value = d3.select('#selector_b').node().value;
var A_regex = new RegExp(escapeRegExp(A_value), "gi");
var B_regex = new RegExp(escapeRegExp(B_value), "gi");
// at this point, the line above is the same as: var regex = /#abc#/g;
if ( A_regex.test(feature_value) ) {
//classes.push('A');
} else if ( B_regex.test(feature_value) ) {
classes.push('B');
}
}
};
return classes.join(' ');
})
b.on("mouseover", function(d) { // Bind a function to mouseover
// This will build a table to display the field names and values
var text = "";
var value;
var no_list = ['DND_UUID'];
text += '<div class="detailCard"><table><tbody>';
if (show_list.length > 0) { // if there's a show_list, only show those fields
for (var i = 0; i < show_list.length; i++) {
key = show_list[i];
if (d.properties && d.properties[key]) {
value = d.properties[key];
value = formatValue(value);
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + value + '</td></tr>';
}
}
} else { // if no show_list, show all fields
for (var key in d.properties) {
// except if it's in the no_list
if ( no_list.indexOf(key.toUpperCase()) == -1 ) {
text += '<tr><td class="detailKey">' + key + '</td><td class="detailVal">' + d.properties[key] + '</td></tr>';
}
}
}
mouseinfo.html(text); // Update the mouseinfo div with the dynamic info
G.layers['overlay_b'].ms_layer.selection(param_selection_function_b([]));
});
};
});
map = mapsense.map("#myMap"); // init the map
map.extent(G.home);
if (G.basemap) {
map.add(mapsense.basemap().apiKey(G.key).style(G.basemap));
}
/*
Using two layers (won't see their relative proportions).
We need to class them either A or B.
*/
G.layers['overlay_a'].ms_layer = mapsense.topoJson()
.url(mapsense.url(
G.layers['overlay_a'].url + G.layers['overlay_a'].where + G.layers['overlay_a'].params
)
.hosts(['a', 'b', 'c', 'd']))
.clip(false)
.scale('fixed')
.selection(
param_selection_function([])
);
//map.add(G.layers['overlay_a'].ms_layer);
console.log(G.layers['overlay_b'].url + G.layers['overlay_b'].where + G.layers['overlay_b'].params);
G.layers['overlay_b'].ms_layer = mapsense.topoJson()
.url(mapsense.url(
G.layers['overlay_b'].url + G.layers['overlay_b'].where + G.layers['overlay_b'].params
)
.hosts(['a', 'b', 'c', 'd']))
.clip(false)
.scale('fixed')
.selection(
param_selection_function_b([])
);
console.log(G.layers['overlay_b'].ms_layer);
map.add(G.layers['overlay_b'].ms_layer);
updateQuery();
// change map interaction so users can see the map update when they scroll through the selector fields
map.interact(false);
map.add(mapsense.drag());
map.add(mapsense.wheel());
map.add(mapsense.dblclick());
map.add(mapsense.touch());
//map.add(mapsense.hash());
mapsense.compass().map(map); //enable shift zoom
d3.select('.compass').attr('style','display: none;') // but hide the compass graphic
}
function updateQuery() {
// update the query
var valu_A, valu_B, new_where, new_url;
var body = getBody();
var valu_A = d3.select('#selector_a').node().value;
var valu_B = d3.select('#selector_b').node().value;
new_where = "&where=name=='" + valu_A + "'";
new_url = G.layers['overlay_a'].url + new_where + G.layers['overlay_a'].params;
//console.log(new_url);
// update the layer
G.layers['overlay_a'].ms_layer.url(
mapsense.url(new_url)
.hosts(['a','b','c','d'])
);
new_where = "&where==name=='" + valu_B + "'";
new_url_b = G.layers['overlay_b'].url + new_where + G.layers['overlay_b'].params;
//console.log(new_url_b);
// update the layer
G.layers['overlay_b'].ms_layer.url(
mapsense.url(new_url_b)
.hosts(['a','b','c','d'])
);
//writeUrl();
}
function cycleQuery() {
// update the query
//var new_where = "&where=amenity=='" + d3.select('#selector_a').node().value + "' OR amenity=='" + d3.select('#selector_b').node().value + "'";
if (G.samples_i < G.samples.length-1) {
G.samples_i += 1;
} else {
G.samples_i = 0;
}
var valu_A = G.samples[G.samples_i][0];
var valu_B = G.samples[G.samples_i][1];
var body = getBody();
/*
d3.select('#selector_a').node().value = valu_A;
d3.select('#selector_b').node().value = valu_B;
*/
d3.select(body).node().select('#selector_a').node().value = valu_A;
d3.select(body).node().select('#selector_b').node().value = valu_B;
d3.select('#enter').on('click')();
}
function initSelect() {
// add a select element to the page
d3.select('#control').append('input')
.attr('id','selector_a')
.attr('class','selector A')
;
d3.select('#control').append('input')
.attr('id','selector_b')
.attr('class','selector B')
;
d3.select('#control').append('a')
.attr('id','enter')
.attr('class','button')
.text('Search')
;
d3.select('#control').append('br');
d3.select('#control').append('a')
.attr('id','refresh')
.attr('class','button')
.html('Example')
;
// When the user selects an option, update the class for those features
d3.selectAll('.selector').on('change.query', updateQuery);
d3.selectAll('#enter').on('click', updateQuery);
d3.selectAll('#refresh').on('click', cycleQuery);
}
function escapeRegExp(stringToGoIntoTheRegex) {
return stringToGoIntoTheRegex.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment