SVG version: Planetary Grid Browser I
xxxxxxxxxx
<meta charset="utf-8">
<title>Planetary Grid II</title>
<link rel="stylesheet" href="/darosh/raw/14e2e4e14898f13e13c7/style.css">
<body>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="canvas.min.js"></script>
<script src="/darosh/raw/2d12a584a14910032ab8/togeojson.js"></script>
<script src="/darosh/raw/2fe464efd794bde5ed68/hexakis-icosahedron.js"></script>
<script src="/darosh/raw/14e2e4e14898f13e13c7/config.js"></script>
<script src="/darosh/raw/14e2e4e14898f13e13c7/utils.js"></script>
<script src="/darosh/raw/14e2e4e14898f13e13c7/legend.js"></script>
<script src="/darosh/raw/14e2e4e14898f13e13c7/list.js"></script>
<script src="/darosh/raw/14e2e4e14898f13e13c7/info.js"></script>
<script src="globe.js"></script>
<script src="map.js"></script>
<script>
(function () {
'use strict';
var widthList = 220;
var margin = 12;
var widthScrollBar = self.frameElement ? 0 : 20;
var widthScreen = Math.floor(Math.max(document.body.clientWidth || 0, 960)) - widthScrollBar;
widthScreen = Math.min(1480, widthScreen);
var heightScreen = Math.max(500, widthScreen / (960 / 480));
margin = widthScreen > 960 ? margin * 2 : margin;
var widthGlobe = 200;
var heightGlobe = 200;
if (heightScreen > 660) {
widthGlobe = 280;
heightGlobe = 280;
}
var widthLegend = 140;
var widthMap = widthScreen - Math.max(widthLegend, widthGlobe / 2) - 2 * margin;
var heightMap = heightScreen - heightGlobe / 2 - 2 * margin;
var selected;
var list;
var cfg = new Config();
cfg.globeRadius = widthGlobe / 2;
cfg.url = 'https://bl.ocks.org/darosh/7b816a50e66bb62208a7';
var canvas = d3.select('body').append('canvas')
.attr('class', 'no-select')
.attr('width', widthMap + widthGlobe / 2)
.attr('height', heightMap + heightGlobe / 2)
.style('margin-left', margin + 'px')
.style('margin-top', margin + 'px');
var ctx = canvas.node().getContext('2d', {alpha: false});
var map = new CanvasMap(ctx, widthMap, heightMap, margin, cfg);
var globeOverlay = d3.select('body')
.append('div')
.attr('class', 'no-select')
.style('position', 'absolute')
.style('border-radius', (widthGlobe / 2) + 'px')
.style('left', (widthMap - widthGlobe / 2 + margin) + 'px')
.style('top', (heightMap - widthGlobe / 2 + margin) + 'px')
.style('width', (widthGlobe) + 'px')
.style('height', (heightGlobe) + 'px');
var globe = new CanvasGlobe(ctx, widthGlobe, heightGlobe, cfg, globeOverlay);
map.drawGlobe = globe.draw;
var svgLegendWrap = d3.select('body').append('svg')
.attr('width', widthLegend)
.attr('height', heightMap - heightGlobe / 2)
.style('position', 'absolute')
.style('left', (widthMap + margin + cfg.lineMid) + 'px')
.style('top', margin + 'px');
var legend = new SvgLegend(svgLegendWrap, cfg, clickedLegend);
cfg.filter = legend.lookFilter;
var svgListWrap = d3.select('body').append('svg')
.attr('width', widthMap - widthGlobe / 2)
.attr('height', 0)
.style('position', 'absolute')
.style('left', margin + 'px')
.style('top', (heightMap + margin + cfg.lineMid) + 'px');
list = new SvgList(svgListWrap,
cfg, widthMap - widthGlobe / 2, widthList,
function (h) {
h = h + margin;
svgListWrap.attr('height', h);
d3.select(self.frameElement).style('height', (h + heightMap + 2 * margin) + 'px');
},
selectedPlace
);
var info = new HtmlInfo(d3.select('body').append('div')
.style('position', 'absolute')
.style('left', (2 * margin) + 'px')
.style('top', (2 * margin) + 'px')
.style('border', cfg.frameLineWidth + 'px solid ' + cfg.colors.frame)
.style('padding', (cfg.titleSize * 0.75) + 'px')
.style('min-width', (cfg.titleSize * 8) + 'px')
.style('background-color', cfg.colors.bg),
cfg
);
var controls = d3.select('body').append('svg')
.attr('width', 70)
.attr('height', 22)
.style('position', 'absolute')
.style('left', (margin * 1.5) + 'px')
.style('top', (heightMap + margin * .5 - 22) + 'px');
Utils.svgControls(controls, setIndex, map.reset);
map.clickedPoint = function (p) {
selectedPlace(p);
};
map.onZoomed = globe.setZoom;
globe.onZoomed = map.setZoom;
globe.canZoom = function (i) {
var p = map.projection(i);
return !isNaN(p[0]) && !isNaN(p[1]);
};
if (self.frameElement) {
self.frameElement.focus();
}
d3.select('body').on('keydown', function () {
var i = null;
if (d3.event.keyCode === 37) {
i = -1;
} else if (d3.event.keyCode === 39) {
i = +1;
} else if (d3.event.keyCode === 27 && selected) {
selectedPlace(selected);
map.update(1);
d3.event.stopPropagation();
d3.event.preventDefault();
}
if (i !== null) {
setIndex(i);
d3.event.stopPropagation();
d3.event.preventDefault();
}
});
map.update(1);
d3.json('/darosh/raw/14e2e4e14898f13e13c7/mercator-countries.json', function (topo) {
topojson.presimplify(topo);
map.countriesDatum = topojson.mesh(topo, topo.objects.countries);
map.update(1);
});
d3.json('/darosh/raw/14e2e4e14898f13e13c7/mercator-land.json', function (topo) {
topojson.presimplify(topo);
map.landDatum = topojson.feature(topo, topo.objects.land);
map.update(1);
});
d3.json('/darosh/raw/14e2e4e14898f13e13c7/land.json', function (topo) {
globe.landDatum = topojson.feature(topo, topo.objects.land);
map.update(1);
});
d3.xml('/darosh/raw/2d12a584a14910032ab8/places.kml', function (xml) {
var geo = toGeoJSON.kml(xml);
Utils.parsePlaces(geo);
map.geo = geo;
if (list) {
list.update(geo);
}
cfg.filtered = geo.features;
map.update(1);
});
function clickedLegend() {
map.update(1);
list.filter(legend.lookShapes);
}
function selectedPlace(d) {
if (list) {
list.selection(selected, d);
}
if (d === selected) {
d = null;
}
globe.selection = d;
info.update(d);
selected = d;
map.zoomTo(d, info.size);
}
function setIndex(i) {
var f = cfg.filtered;
var c = f.indexOf(selected);
c = c === -1 ? 0 : (c + i);
c = (c + f.length) % f.length;
if (list) {
list.selection(selected, f[c]);
}
info.update(f[c]);
globe.selection = f[c];
setTimeout(function () {
map.zoomTo(f[c], info.size);
}, 50);
selected = f[c];
}
})();
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js
https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js