Skip to content

Instantly share code, notes, and snippets.

@rochoa
Forked from tyrasd/README.md
Last active September 10, 2015 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rochoa/b489be995789aae920d7 to your computer and use it in GitHub Desktop.
Save rochoa/b489be995789aae920d7 to your computer and use it in GitHub Desktop.
Map & Globe

modified version of http://bl.ocks.org/curran/01aa2685f083b6c1b9fb with the map's bounding box on the globe

original readme follows:

--

Pan and zoom in the map on the left to rotate the globe.

Click and drag the globe to pan on the map.

An example that shows a Chiasm plugin based on Leaflet.js alongside a Chiasm globe plugin based on the D3 example This is a Globe.

The Chiasm plugins demonstrated here are

  • leaflet A Leaflet-based geographic map component.

  • globe A D3 black and white globe renderer that uses HTML5 Canvas.

  • layout A plugin for nested box layout of arbitrary components.

  • links A plugin for connecting components together. This links the pan and zoom between the globe and the map.

web counter
// This is an example Chaism plugin that uses Leaflet.js.
function ChiasmLeaflet() {
var my = ChiasmComponent({ });
// Expose a div element that will be added to the Chiasm container.
// This is a special property that Chiasm looks for after components are constructed.
my.el = document.createElement("div");
// When you zoom out all the way, this line makes the background black
// (by default it is gray).
d3.select(my.el).style("background-color", "black");
var map = L.map(my.el, {
attributionControl: false
}).setView([39.859, -4.592], 5);
// Add the black & white style map layer.
// Found by browsing http://leaflet-extras.github.io/leaflet-providers/preview/
L.tileLayer("http://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png").addTo(map);
// Also try this http://{s}.tiles.earthatlas.info/natural-earth/{z}/{x}/{y}.png
function getCenter(){
var center = map.getCenter();
return [center.lng, center.lat];
}
function setCenter(center){
map.off("move", onMove);
map.panTo(L.latLng(center[1], center[0]), {
animate: false
});
my.bounds = map.getBounds();
map.on("move", onMove);
}
map.on("move", onMove);
function onMove(){
my.center = getCenter();
my.zoom = map.getZoom();
my.bounds = map.getBounds();
}
// If the center was set externally, pan the map to that center.
my.when("center", function (center){
if(!equal(center, getCenter())){
setCenter(center);
}
});
function equal(a, b){
return JSON.stringify(a) === JSON.stringify(b);
}
my.when("box", function (box) {
d3.select(my.el)
.style("width", box.width + "px")
.style("height", box.height + "px");
map.invalidateSize();
});
return my;
}
// This is an example Chiasm plugin based on this D3 Canvas example:
// http://bl.ocks.org/mbostock/ba63c55dd2dbc3ab0127
function Globe (){
var my = ChiasmComponent({
backgroundColor: "black",
foregroundColor: "white",
center: [0, 0],
bounds: null,
zoom: 1,
sens: 0.25
});
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var projection = d3.geo.orthographic()
.clipAngle(90);
var path = d3.geo.path()
.projection(projection)
.context(context);
// Interaction that lets the user rotate the globe.
// Draws from http://bl.ocks.org/KoGor/5994804
d3.select(canvas)
.call(d3.behavior.drag()
.origin(function() {
var r = projection.rotate();
return {
x: r[0] / my.sens,
y: -r[1] / my.sens
};
})
.on("drag", function() {
var lng = -d3.event.x * my.sens;
var lat = d3.event.y * my.sens;
// Disallow rotation beyond the poles.
lat = lat > 89 ? 89 : lat < -89 ? -89 : lat;
my.center = [ lng, lat ];
}));
// Hand off the DOM element to the Chiasm layout plugin, which will inject it
// into the parent container for us when we specify the special property `el`.
my.el = canvas;
// The following will all change at runtime, but they are set to some value to
// handle the case that the render function gets run before they are updated.
my.box = {
width: 960,
height: 600
};
my.radius = my.box.height / 2 - 5;
my.scale = my.radius;
my.when("box", function (box){
canvas.width = box.width;
canvas.height = box.height;
projection.translate([box.width / 2, box.height / 2]);
my.radius = box.height / 2 - 5;
});
my.when("radius", function (radius){
my.scale = radius;
});
my.when("bounds", function (bounds){
my.bounds = bounds;
});
my.when("scale", function (scale){
projection.scale(my.scale);
});
my.when("center", function (center){
var lat = center[1];
my.rotate = [ -center[0], -center[1] ];
});
my.when("rotate", function (rotate){
projection.rotate(rotate);
});
function toRadians(deg){
return deg / 180 * Math.PI;
}
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
var land = topojson.feature(world, world.objects.land);
d3.timer(function(elapsed) {
context.fillStyle = my.backgroundColor;
context.fillRect(0, 0, my.box.width, my.box.height);
context.fillStyle = my.foregroundColor;
context.strokeStyle = my.foregroundColor;
context.beginPath();
path(land);
context.fill();
// Stop the code from crashing with transient states that happen on page load.
var radius = my.radius < 1 ? 1 : my.radius;
context.beginPath();
context.arc(my.box.width / 2, my.box.height / 2, radius, 0, 2 * Math.PI, true);
context.lineWidth = 2.5;
context.stroke();
// This makes the circle invert whatever color is underneath it.
context.save();
context.globalCompositeOperation = "difference";
context.strokeStyle = "white";
// Draw the bounding box that represents the current map view.
context.beginPath();
if (my.bounds) {
path({type: "Polygon", coordinates: [[
[my.bounds.getWest(), my.bounds.getSouth()],
[my.bounds.getEast(), my.bounds.getSouth()],
[my.bounds.getEast(), my.bounds.getNorth()],
[my.bounds.getWest(), my.bounds.getNorth()],
[my.bounds.getWest(), my.bounds.getSouth()]
]]});
}
context.lineWidth = 2.5;
context.stroke();
// This is the inverse of context.save(), it pops off the context stack so
// we get back whatever the previous value was for
// globalCompositeOperation.
context.restore();
});
});
return my;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Map & Globe</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<!-- Leaflet.js, a geographic mapping library. -->
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.5/leaflet.js"></script>
<!-- A functional reactive model library. github.com/curran/model -->
<script src="http://curran.github.io/model/cdn/model-v0.2.4.js"></script>
<!-- Chiasm core and plugins. github.com/chiasm-project -->
<script src="http://chiasm-project.github.io/chiasm/chiasm-v0.2.0.js"></script>
<script src="http://chiasm-project.github.io/chiasm-component/chiasm-component-v0.2.0.js"></script>
<script src="http://chiasm-project.github.io/chiasm-layout/chiasm-layout-v0.2.1.js"></script>
<!-- Custom Chiasm plugins for this example. -->
<script src="links.js"></script>
<script src="globe.js"></script>
<script src="chiasm-leaflet.js"></script>
<style>
body {
background-color: black;
}
/* Make the chart container fill the page using CSS. */
#chiasm-container {
position: fixed;
left: 20px;
right: 20px;
top: 20px;
bottom: 20px;
}
</style>
</head>
<body>
<div id="chiasm-container"></div>
<script>
var chiasm = Chiasm();
chiasm.plugins.layout = ChiasmLayout;
chiasm.plugins.links = Links;
chiasm.plugins.globe = Globe;
chiasm.plugins.leaflet = ChiasmLeaflet;
chiasm.setConfig({
"layout": {
"plugin": "layout",
"state": {
"containerSelector": "#chiasm-container",
"layout": {
"orientation": "horizontal",
"children": [
"leafletMap",
"d3Globe",
]
}
}
},
"leafletMap": {
"plugin": "leaflet",
"state": { }
},
"d3Globe": {
"plugin": "globe",
"state": {}
},
"links": {
"plugin": "links",
"state": {
"bindings": [
"leafletMap.center -> d3Globe.center",
"leafletMap.zoom -> d3Globe.zoom",
"leafletMap.bounds -> d3Globe.bounds",
"d3Globe.center -> leafletMap.center"
]
}
}
});
</script>
</body>
</html>
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