|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>dc.js megamix</title> |
|
<link rel="stylesheet" type="text/css" href="https://dc-js.github.io/dc.js/css/dc.css" /> |
|
<link rel="stylesheet" type="text/css" href="http://dc-js.github.io/dc.graph.js/css/dc.graph.css"/> |
|
<link rel="stylesheet" type="text/css" href="http://dc-js.github.io/dc.leaflet.js/css/leaflet.css" /> |
|
|
|
<script src="https://dc-js.github.io/dc.js/js/d3.js"></script> |
|
<script src="https://dc-js.github.io/dc.js/js/crossfilter.js"></script> |
|
<script src="https://dc-js.github.io/dc.js/js/dc.js"></script> |
|
<script src="http://dc-js.github.io/dc.graph.js/js/chart.registry.js"></script> |
|
<script src="http://dc-js.github.io/dc.graph.js/js/dc.graph.js"></script> |
|
<script src="http://dc-js.github.io/dc.graph.js/js/cola.js"></script> |
|
<script src="http://dc-js.github.io/dc.leaflet.js/js/leaflet-src.js"></script> |
|
<script src="http://dc-js.github.io/dc.leaflet.js/js/dc.leaflet.js"></script> |
|
|
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<div id="graph" style="float:left"></div> |
|
<div id="map"></div> |
|
<div id="bars" style="clear:left"></div> |
|
<div id="pie"></div> |
|
<div id="row"></div> |
|
<div id="scatter"></div> |
|
<script> |
|
var center = [39.8333333,-98.585522]; |
|
|
|
function normal(N) { // generate normal distribution of integers in [0,N) |
|
var rand = d3.random.normal(N/2, N/6); |
|
return function() { |
|
var r = rand(); |
|
if(r < 0) |
|
return 0; |
|
else if(r > N-1) |
|
return N-1; |
|
else return Math.floor(r); |
|
} |
|
} |
|
function remove_empty_bins(source_group, field) { |
|
return { |
|
all:function () { |
|
return source_group.all().filter(function(d) { |
|
//return Math.abs(d.value) > 0.00001; // if using floating-point numbers |
|
return d.value[field] !== 0; // if integers only |
|
}); |
|
} |
|
}; |
|
} |
|
|
|
var N = 5000, NW = 100, NE = 90, // number of data, number of (virtual) widgets, number of edges |
|
rndVW = normal(NW); |
|
|
|
var edges = d3.range(NE).map(function(i) { |
|
return {key: i, value: {source: rndVW(), target: rndVW()}}; |
|
}); |
|
// data from http://www.geomidpoint.com/random/ - center 39.8333333,-98.585522, radius 1500mi |
|
d3.csv('sites.csv', function(error, sites) { |
|
var rndS = normal(sites.length), rndX = normal(5), rndY = normal(7), rndA = normal(100), rndB = normal(100); |
|
sites = d3.shuffle(sites); |
|
var data = []; |
|
for(var i = 0; i < N; ++i) { |
|
var s = rndS(), |
|
site = sites[s]; |
|
data.push({ |
|
lat: +site.lat, |
|
long: +site.long, |
|
widget: rndVW(), |
|
x: rndX(), |
|
y: rndY(), |
|
a: rndA(), |
|
b: rndB(), |
|
health: Math.random() |
|
}); |
|
} |
|
|
|
var cf = crossfilter(data); |
|
var locDim = cf.dimension(function(d) { return d.lat + ',' + d.long; }), |
|
locGroup = locDim.group(); |
|
|
|
var tiles=function(map) { |
|
L.tileLayer('https://api.mapbox.com/v4/mapbox.outdoors/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoiZm91cnRoYXJrIiwiYSI6ImNqNXNoMGNpODE3MDczMm11bGppejUydnYifQ.CbZ-bY4pwfUvkTncEoJWPA', { |
|
attribution: '<a href=\"https://www.mapbox.com/about/maps/\" target=\"_blank\">© Mapbox</a> <a href=\"https://openstreetmap.org/about/\" target=\"_blank\">© OpenStreetMap</a>' |
|
}).addTo(map); |
|
}; |
|
|
|
|
|
dc_leaflet.bubbleChart('#map') |
|
.width(480).height(480) |
|
.center(center) |
|
.zoom(3) |
|
.tiles(tiles) |
|
.dimension(locDim) |
|
.group(locGroup) |
|
.r(d3.scale.sqrt().domain([0,100]).range([5,15])) |
|
.unselectedColor('#68e') |
|
; |
|
|
|
var widgetDim = cf.dimension(function(d) { return d.widget; }), |
|
widgetGroup = widgetDim.group().reduce( |
|
function(p, v) { // add |
|
p.sumhealth += v.health; |
|
++p.n; |
|
return p; |
|
}, |
|
function(p, v) { // remove |
|
p.sumhealth -= v.health; |
|
--p.n; |
|
return p; |
|
}, |
|
function() { // init |
|
return {sumhealth: 0, n: 0}; |
|
} |
|
), |
|
nonemptyWidgets = remove_empty_bins(widgetGroup, 'n') |
|
var edgeDim = {}, // static/unused |
|
edgeGroup = { |
|
all: function() { |
|
return edges; |
|
} |
|
}; |
|
var healthColors = d3.scale.linear() |
|
.domain([0.25, 0.5, 0.75]).clamp(true) |
|
.range(["red", "white", "green"]) |
|
var engine =dc_graph.cola_layout() |
|
.baseLength(15) |
|
var diagram = dc_graph.diagram('#graph') |
|
.width(480).height(480) |
|
.nodeDimension(widgetDim).nodeGroup(nonemptyWidgets) |
|
.edgeDimension(edgeDim).edgeGroup(edgeGroup) |
|
.layoutEngine(engine) |
|
.initLayoutOnRedraw(true) |
|
.timeLimit(2000) |
|
.nodeRadius(n => 2*Math.sqrt(n.value.n)) |
|
.nodeFill(n => n.value.sumhealth / n.value.n) |
|
.nodeFillScale(healthColors) |
|
.edgeKey(e => String(e.key)) |
|
.edgeSource(e => e.value.source) |
|
.edgeTarget(e => e.value.target) |
|
.nodeStrokeWidth(1) |
|
.nodeOpacity(0.25) |
|
.altKeyZoom(true) |
|
.induceNodes(true); |
|
var select_nodes = dc_graph.select_nodes({ |
|
nodeOpacity: 1 |
|
}) |
|
.noneIsAll(true) |
|
.autoCropSelection(false); |
|
diagram.child('select-nodes', select_nodes); |
|
diagram.child('filter-selection', dc_graph.filter_selection()); |
|
|
|
var healthDim = cf.dimension(function(d) { return d.health; }), |
|
healthGroup = healthDim.group(function(d) { return Math.floor(d*10)/10; }) |
|
|
|
var bars = dc.barChart('#bars') |
|
.width(300).height(150) |
|
.dimension(healthDim) |
|
.group(healthGroup) |
|
.x(d3.scale.linear()) |
|
.xUnits(dc.units.fp.precision(0.1)) |
|
.colors(healthColors) |
|
.colorAccessor(function(d) { |
|
return d.key; |
|
}) |
|
.elasticX(true).elasticY(true); |
|
|
|
var xDim = cf.dimension(function(d) { return d.x; }), |
|
xGroup = xDim.group(); |
|
var pie = dc.pieChart('#pie') |
|
.width(150).height(150) |
|
.dimension(xDim) |
|
.group(xGroup) |
|
.colors(d3.scale.ordinal().range(d3.shuffle(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00']))); |
|
|
|
var yDim = cf.dimension(function(d) { return d.y; }), |
|
yGroup = xDim.group(); |
|
var row = dc.rowChart('#row') |
|
.width(350).height(150) |
|
.dimension(yDim) |
|
.group(yGroup) |
|
.colors(d3.scale.ordinal().range(d3.shuffle(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628']))); |
|
|
|
var abDim = cf.dimension(function(d) { return [d.a, d.b]; }), |
|
abGroup = abDim.group(); |
|
var scatter = dc.scatterPlot('#scatter') |
|
.width(960 - 300 - 150 - 350).height(150) |
|
.margins({top: 0, left: 0, right: 0, bottom: 0}) |
|
.dimension(abDim) |
|
.group(abGroup) |
|
.x(d3.scale.linear()) |
|
.y(d3.scale.linear()) |
|
.elasticX(true) |
|
.elasticY(true) |
|
.ordinalColors(['#4daf4a']) |
|
.symbolSize(2) |
|
|
|
dc.renderAll(); |
|
|
|
}); |
|
</script> |
|
</body> |