Files @ abaf1f269af7
Branch filter:

Location: FVDE/ennstatus/ennstatus/static/js/worldmap.js

abaf1f269af7 4.6 KiB application/javascript Show Annotation Show as Raw Download as Raw
Dennis Fink
Merged dev
/* Ënnstatus
   Copyright (C) 2015  Dennis Fink

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


d3.select(window).on("resize", throttle);
	
var zoom = d3.behavior.zoom()
	.scaleExtent([1, 9])
	.on("zoom", move);

var width = document.getElementById('chart').offsetWidth;
var height = width / 2;

var topo, projection, path, svg, g;

var graticule = d3.geo.graticule();

var tooltip = d3.select("#chart").append("div").attr("class", "tooltip hidden");

setup(width, height);

function setup(width, height) {
	projection = d3.geo.mercator()
	 	.translate([(width / 2), (height / 2)])
	 	.scale(width / 2 / Math.PI)
	
	path = d3.geo.path().projection(projection);

	svg = d3.select("#chart").append("svg")
		.attr("width", width)
		.attr("height", height)
		.call(zoom)
		.append("g");

	g = svg.append("g")
		.on("click", click);
}

d3.json("/static/data/world-topo-min.json", function(error, world) {
	var countries = topojson.feature(world, world.objects.countries).features;

	topo = countries;
	draw(topo);
});

function draw(topo) {

	svg.append("path")
		.datum(graticule)
		.attr("class", "graticule")
		.attr("d", path);

	g.append("path")
		.datum({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]})
		.attr("class", "equator")
		.attr("d", path);

	var country = g.selectAll(".country").data(topo);
	d3.json("/data/worldmap", function(err, data) {


		var colorscale = d3.scale.threshold().domain(d3.range(1, (data.max+1)/3).map(function(n) { var a=1, b=1, f=1; for(var i = 2; i <= n; i++) { f = a+b; a=b; b=f } return f;})).range([
			"#aeffb9",
			"#87ff97",
			"#60ff76",
			"#38ff54",
			"#11ff32",
			"#00e920",
			"#00c21b",
			"#009a15",
			"#008713",
			"#007310",
			"#00600d",
			"#004c0a"
		])

		country.enter().insert("path")
			.attr("class", "country")
			.attr("d", path)
			.attr("id", function(d, i) { return d.id; })
			.style("fill", function(d, i) { 
				if (d.properties.name in data) {
					return colorscale(data[d.properties.name]['total']);
				} else {
					return "#fdf6e3";
				}
			});

		var tooltip = d3.select('#chart').append('div')
			.attr('class', 'tooltip')

		country.on("mousemove", function(d, i) {
	
			var mouse = d3.mouse(svg.node()).map(function(d) { return parseInt(d); });

			tooltip.classed("hidden", false)
				.attr("style", "left:"+(mouse[0]+40)+"px;top:"+mouse[1]+"px")
				.html(function() {
					if (d.properties.name in data) {
						var text = "<b>" + d.properties.name + "</b>" + "<br>Total servers: " + data[d.properties.name]['total']
						if ('bridge' in data[d.properties.name]) {
							text = text + "<br>Bridge servers: " + data[d.properties.name]['bridge']
						}
						if ('exit' in data[d.properties.name]) {
							text = text + "<br>Exit servers: " + data[d.properties.name]['exit']
						}
						if ('relay' in data[d.properties.name]) {
							text = text + "<br>Relay server: " + data[d.properties.name]['relay']
						}
						return text
					} else {
						return "<b>" + d.properties.name + "</b>"
					}
				})
		})
		.on("mouseout", function(d, i) {
			tooltip.classed("hidden", true);
		});


	});
};


function redraw() {
  width = document.getElementById('chart').offsetWidth;
  height = width / 2;
  d3.select('svg').remove();
  setup(width,height);
  draw(topo);
}


function move() {

  var t = d3.event.translate;
  var s = d3.event.scale; 
  zscale = s;
  var h = height/4;


  t[0] = Math.min(
    (width/height)  * (s - 1), 
    Math.max( width * (1 - s), t[0] )
  );

  t[1] = Math.min(
    h * (s - 1) + h * s, 
    Math.max(height  * (1 - s) - h * s, t[1])
  );

  zoom.translate(t);
  g.attr("transform", "translate(" + t + ")scale(" + s + ")");

  //adjust the country hover stroke width based on zoom level
  d3.selectAll(".country").style("stroke-width", 1.5 / s);

}


var throttleTimer;
function throttle() {
	  window.clearTimeout(throttleTimer);
	      throttleTimer = window.setTimeout(function() {
		            redraw();
			        }, 200);
}

function click() {
	  var latlon = projection.invert(d3.mouse(this));
	    console.log(latlon);
}