Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mukhtyar/28a51aa05c462f5ddc82 to your computer and use it in GitHub Desktop.
Save mukhtyar/28a51aa05c462f5ddc82 to your computer and use it in GitHub Desktop.
<!-- Based on following blocks:
mapsense-examples’s block
http://bl.ocks.org/mapsense-examples/be0ad69cbea40d842726
zanarmstrong’s block
http://bl.ocks.org/zanarmstrong/ddff7cd0b1220bc68a58
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link rel="stylesheet" href="http://leafletjs.com/dist/leaflet.css" media="screen" type="text/css">
<link rel="stylesheet" href="https://developer.mapsense.co/mapsense.css" media="screen" type="text/css">
<link rel="stylesheet" href="slider.css">
<script src='http://d3js.org/d3.v3.min.js' type="text/javascript"></script>
<script src='http://d3js.org/topojson.v1.min.js' type="text/javascript"></script>
<script src='http://leafletjs.com/dist/leaflet.js' type="text/javascript"></script>
<script src='L.TileLayer.d3_JSON_mapsense.js' type="text/javascript"></script>
<style>
html, body {
width: 100%; height: 100%; margin: 0; padding: 0;
}
#myMap {
width: 100%; height: 800px; margin-top: 50px; padding: 0;
}
#options {
width: 100%; height: 10%;
}
.leaflet-container {
background: transparent;
outline: 0;
}
.mapsense-light.tile-background {
fill: none;
}
.mapsense-light.roads {
stroke: #945454;
}
.tile-slider {
padding: 6px 8px;
font: 14px/16px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255,255,255,0.8);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
}
.tile-slider h4 {
margin: 0 0 5px;
color: #777;
}
.tile-slider {
margin-bottom: 50px;
}
</style>
</head>
<body>
<div id="options">
<h1 style="color:white;margin-left:20px;font-size:3em;">Cal-Adapt CMIP5 LOCA CCSM4 Maximum Temperature</h1>
<select id = "month" style="margin-left:20px;font-size:1em;">
<option value="01">January</option>
<option value="02">February</option>
<option value="03">March</option>
<option value="04">April</option>
<option value="05">May</option>
<option value="06">June</option>
<option value="07" selected="selected">July</option>
<option value="08">August</option>
<option value="09">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
<select id = "year" style="margin-left:20px;font-size:1em;">
<option value="1950">1950</option>
<option value="1960">1960</option>
<option value="1970" selected="selected">1970</option>
<option value="1980">1980</option>
<option value="1990">1990</option>
<option value="2000">2000</option>
<option value="2002">2002</option>
<option value="2005">2005</option>
</select>
</div>
<div id="myMap"></div>
<script>
var map = L.map('myMap').setView([38.8, -121.5], 7);
var my_key = "key-b92646a22593424f8c3a42c1b9e540ff";
new L.tileLayer("http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg", {
attribution: '<a href="http://developer.mapquest.com/web/products/open/map</a>Mapquest</a>',
subdomains: ["otile1", "otile2", "otile3", "otile4"],
opacity: 0.5
}).addTo(map);
var year = d3.select('#year').property('value');
var month = d3.select('#month').property('value');
console.log(year, month);
var tasmaxUrl = "https://dev-ecoengine.berkeley.edu/api/tiles/tasmax-" + year + "-" + month + "/{z}/{x}/{y}/"
var tasmax = new L.tileLayer(tasmaxUrl, {
attribution: '<a href="http://ecoengine.berkeley.edu</a>Cal-Adapt</a>'
}).addTo(map);
// Hat Tip! http://bl.ocks.org/NelsonMinar/5624141
// Add a fake GeoJSON line to coerce Leaflet into creating the <svg> tag that d3_geoJson needs
new L.geoJson({"type": "LineString","coordinates":[[0,0],[0,0]]}).addTo(map);
var mapsense_url = "https://{s}-api.mapsense.co/explore/api/universes/mapsense.earth/{z}/{x}/{y}.topojson?s=10&ringSpan=8&api-key=" + my_key;
mapsense_url += "&where=layer=='roads'";
new L.TileLayer.d3_JSON(mapsense_url, {
attribution: '<a target="_blank" href="https://developer.mapsense.co/tileViewer/?tileset=mapsense.earth">©Mapsense ©OpenStreetMap</a>',
// https://developer.mapsense.co/documentation/basemap
//mapsenseStyle: "vintage" // choose a basemap style, or style your own at styler.mapsense.co
}).addTo(map);
function updateTiles(month, year) {
console.log(month, year);
var url = "https://dev-ecoengine.berkeley.edu/api/tiles/tasmax-" + year + "-" + month + "/{z}/{x}/{y}/"
tasmax.setUrl(url);
}
// handle on click event
d3.select('#month')
.on('change', function() {
var currentMonth = d3.select(this).property('value');
updateTiles(currentMonth, year);
});
// handle on click event
d3.select('#year')
.on('change', function() {
var currentYear = d3.select(this).property('value');
updateTiles(month, currentYear);
});
</script>
</body>
</html>
<!-- Based on following blocks:
mapsense-examples’s block
http://bl.ocks.org/mapsense-examples/be0ad69cbea40d842726
zanarmstrong’s block
http://bl.ocks.org/zanarmstrong/ddff7cd0b1220bc68a58
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link rel="stylesheet" href="http://leafletjs.com/dist/leaflet.css" media="screen" type="text/css">
<link rel="stylesheet" href="https://developer.mapsense.co/mapsense.css" media="screen" type="text/css">
<link rel="stylesheet" href="slider.css">
<script src='http://d3js.org/d3.v3.min.js' type="text/javascript"></script>
<script src='http://d3js.org/topojson.v1.min.js' type="text/javascript"></script>
<script src='http://leafletjs.com/dist/leaflet.js' type="text/javascript"></script>
<script src='L.TileLayer.d3_JSON_mapsense.js' type="text/javascript"></script>
<style>
html, body, #myMap { width: 100%; height: 100%; margin: 0; padding: 0;}
.leaflet-container {
background: transparent;
outline: 0;
}
.mapsense-light.tile-background {
fill: none;
}
.mapsense-light.roads {
stroke: #945454;
}
.tile-slider {
padding: 6px 8px;
font: 14px/16px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255,255,255,0.8);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
}
.tile-slider h4 {
margin: 0 0 5px;
color: #777;
}
.tile-slider {
margin-bottom: 50px;
}
</style>
</head>
<body>
<div id="myMap"></div>
<script>
var map = L.map('myMap').setView([38.8, -121.5], 7);
var my_key = "key-b92646a22593424f8c3a42c1b9e540ff";
new L.tileLayer("http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg", {
attribution: '<a href="http://developer.mapquest.com/web/products/open/map</a>Mapquest</a>',
subdomains: ["otile1", "otile2", "otile3", "otile4"],
opacity: 0.5
}).addTo(map);
var tasmax = new L.tileLayer("https://dev-ecoengine.berkeley.edu/api/tiles/tasmax-1954-07/{z}/{x}/{y}/", {
attribution: '<a href="http://ecoengine.berkeley.edu</a>Cal-Adapt</a>'
}).addTo(map);
// Hat Tip! http://bl.ocks.org/NelsonMinar/5624141
// Add a fake GeoJSON line to coerce Leaflet into creating the <svg> tag that d3_geoJson needs
new L.geoJson({"type": "LineString","coordinates":[[0,0],[0,0]]}).addTo(map);
var mapsense_url = "https://{s}-api.mapsense.co/explore/api/universes/mapsense.earth/{z}/{x}/{y}.topojson?s=10&ringSpan=8&api-key=" + my_key;
mapsense_url += "&where=layer=='roads'";
new L.TileLayer.d3_JSON(mapsense_url, {
attribution: '<a target="_blank" href="https://developer.mapsense.co/tileViewer/?tileset=mapsense.earth">©Mapsense ©OpenStreetMap</a>',
// https://developer.mapsense.co/documentation/basemap
//mapsenseStyle: "vintage" // choose a basemap style, or style your own at styler.mapsense.co
}).addTo(map);
var info = L.control({position: 'bottomleft'});
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'tile-slider'); // create a div with a class "tile-slider"
this.update();
return this._div;
};
// method that we will use to update the control based on feature properties passed
info.update = function (props) {
this._div.innerHTML = '<h4>Year Slider</h4>';
};
info.addTo(map);
//year slider code
formatDate = d3.time.format("%Y");
// parameters
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = 500 - margin.left - margin.right,
height = 100 - margin.bottom - margin.top;
// scale function
var timeScale = d3.time.scale()
.domain([new Date('1951'), new Date('2006')])
.range([0, width])
.clamp(true);
// initial value
var startValue = timeScale(new Date('1955'));
startingValue = new Date('1955');
//////////
// defines brush
var brush = d3.svg.brush()
.x(timeScale)
.extent([startingValue, startingValue])
.on("brush", brushed);
var svg = d3.select(".tile-slider").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
// classic transform to position g
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
// put in middle of screen
.attr("transform", "translate(0," + height / 2 + ")")
// inroduce axis
.call(d3.svg.axis()
.scale(timeScale)
.orient("bottom")
.tickFormat(function(d) {
return formatDate(d);
})
.tickSize(0)
.tickPadding(12)
.tickValues([timeScale.domain()[0], timeScale.domain()[1]]))
.select(".domain")
.select(function() {
console.log(this);
return this.parentNode.appendChild(this.cloneNode(true));
})
.attr("class", "halo");
var slider = svg.append("g")
.attr("class", "slider")
.call(brush);
slider.selectAll(".extent,.resize")
.remove();
slider.select(".background")
.attr("height", height);
var handle = slider.append("g")
.attr("class", "handle")
handle.append("path")
.attr("transform", "translate(0," + height / 2 + ")")
.attr("d", "M 0 -20 V 20")
handle.append('text')
.text(startingValue)
.attr("transform", "translate(" + (-18) + " ," + (height / 2 - 25) + ")");
slider
.call(brush.event)
function brushed() {
var value = brush.extent()[0];
var year = formatDate(value);
if (d3.event.sourceEvent) { // not a programmatic event
value = timeScale.invert(d3.mouse(this)[0]);
brush.extent([value, value]);
}
handle.attr("transform", "translate(" + timeScale(value) + ",0)");
handle.select('text').text(formatDate(value));
var tasmaxUrl = "https://dev-ecoengine.berkeley.edu/api/tiles/tasmax-" + year + "-07/{z}/{x}/{y}/"
tasmax.setUrl(tasmaxUrl);
}
</script>
</body>
</html>
L.TileLayer.d3_JSON = L.TileLayer.extend({
//extending L.TileLayer to support topoJSON and geoJSON vector sources
//rendering with d3, borrows from zjonsson & https://github.com/glenrobertson/leaflet-tilelayer-geojson/
onAdd: function(map) {
var map_container_svg = d3.select(map._container).select("svg");
L.TileLayer.prototype.onAdd.call(this, map);
this.mapsenseStyle = this.options.mapsenseStyle || 'light';
this._path = d3.geo.path().projection({
stream: function(stream) {
// no sampling along great arc
// just a pure projection, without the default d3 projection-stream pipeline
// so, long lines don't make curves, i.e. they obey the mercator projection
return {
point: function(x, y) {
var p = map.latLngToLayerPoint(new L.LatLng(y, x));
stream.point(p.x, p.y);
},
lineStart: stream.lineStart,
lineEnd: stream.lineEnd,
polygonStart: stream.polygonStart,
polygonEnd: stream.polygonEnd,
sphere: stream.sphere
};
}
});
this.on("tileunload", function(d) {
if (d.tile.xhr) d.tile.xhr.abort();
if (d.tile.nodes) d.tile.nodes.remove();
d.tile.nodes = null;
d.tile.xhr = null;
});
},
_loadTile: function(tile, tilePoint) {
var self = this;
this._adjustTilePoint(tilePoint);
var mapsenseStyle = this.mapsenseStyle;
if (!tile.nodes && !tile.xhr) {
tile.xhr = d3.json(this.getTileUrl(tilePoint), function(data) {
var geoJson;
if (data === '') {
// Ignore empty submissions
} else {
geoJson = topo2Geo(data);
}
tile.xhr = null;
nwPoint = tilePoint.multiplyBy(256);
sePoint = nwPoint.add([256, 256]);
nw = map.unproject(nwPoint);
se = map.unproject(sePoint);
var point = map.latLngToLayerPoint(new L.LatLng(nw.lat, nw.lng));
var tile_coords = "tile_" + point.x + "_" + point.y;
d3.select(map._container).select("svg")
.append("clipPath")
.attr("id", tile_coords)
.attr("style", "fill: none; stroke: pink; transform: translate(" + point.x + "px, " + point.y + "px); -webkit-transform: translate(" + point.x + "px, " + point.y + "px);")
.append("rect")
.attr("width", "256")
.attr("height", "256");
d3.select(map._container).select("svg")
.append("rect")
.attr("style", "transform: translate(" + point.x + "px, " + point.y + "px); -webkit-transform: translate(" + point.x + "px, " + point.y + "px);")
.attr("width", "256")
.attr("height", "256")
.attr("class", "mapsense-"+self.mapsenseStyle +" tile-background");
tile.nodes = d3.select(map._container).select("svg").append("g");
// tile.nodes is now a bunch of appended g's
var grp = tile.nodes.selectAll("path")
.data(geoJson.features)
.enter()
.append("g")
.attr("class", "groupr");
grp.append("path")
.attr("d", self._path)
.attr("clip-path", "url(#" + tile_coords + ")")
.attr("class", self.options.class)
.attr("class", function(d) { // this data is a bunch of features
var zoomClass = "_" + Math.floor(map.getZoom());
var classes = ['mapsense-'+self.mapsenseStyle];
if (d.properties) {
if (d.properties) {
if (d.properties.layer)
classes.push(d.properties.layer);
if (d.properties.natural)
classes.push(d.properties.natural);
if (d.properties.sub_layer)
classes.push(d.properties.sub_layer);
} else {
classes.push('unknown');
}
classes = classes.join(' ');
return classes;
} else {}
});
});
}
}
});
function topologyFeatures(topology) {
function convert(topology, object, layer, features) {
var featureOrCollection = topojson.feature(topology, object),
layerFeatures;
if (featureOrCollection.type === "FeatureCollection") {
layerFeatures = featureOrCollection.features;
} else {
layerFeatures = [featureOrCollection];
}
layerFeatures.forEach(function(f) {
f.properties.layer = layer;
});
features.push.apply(features, layerFeatures);
}
var features = [];
for (var o in topology.objects) {
convert(topology, topology.objects[o], o, features);
}
return features;
}
function topo2Geo(tj) {
var gj = {
type: "FeatureCollection",
features: topologyFeatures(tj)
};
return gj;
}
body {
background-color: #393939;
font-size: 14px;
font-family: 'Raleway', sans-serif;
}
p {
color: white;
margin: 50px;
}
a {
color: #4FDEF2;
}
.axis {
fill: gray;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.axis .halo {
stroke: gray;
stroke-width: 4px;
stroke-linecap: round;
}
.slider .handle path {
stroke: white;
stroke-width: 3px;
stroke-linecap: round;
pointer-events: none;
}
.slider .handle text {
fill: white;
text-align: center;
font-size: 18px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment