Skip to content

Instantly share code, notes, and snippets.

@tyrasd
Forked from curran/README.md
Last active February 1, 2016 08:14
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 tyrasd/e2744ee563f7cab80350 to your computer and use it in GitHub Desktop.
Save tyrasd/e2744ee563f7cab80350 to your computer and use it in GitHub Desktop.

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.
@curran
Copy link

curran commented Sep 9, 2015

Awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment