dc
Version:
A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js
204 lines (193 loc) • 7.8 kB
HTML
<html lang="en">
<head>
<title>dc.js - Scatter Plot Matrix</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../css/dc.css"/>
<style>
html, body {
margin: 0;
width: 100%;
}
code {
color: black;
}
#page {
height: 95vh;
width: 100%;
}
tr.heading td div {
text-align: center;
}
td.heading {
position: relative;
}
tr.row:not(.heading) td.heading div {
white-space: nowrap;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%) rotate(-90deg);
}
.chart-holder {
padding: 0 1em;
}
path.left {
stroke: #1f77b4;
}
path.right {
stroke: #ff7f0e;
}
path.horizontal {
stroke-width: 1;
stroke-opacity: 0.5;
}
path.zero {
stroke-dasharray: 4, 4;
}
path.zero.right {
stroke-dashoffset: 4;
}
path.extreme {
stroke-dasharray: 1, 1;
}
path.extreme.right {
stroke-dashoffset: 1;
}
.axis > path {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript" src="../js/d3.js"></script>
<script type="text/javascript" src="../js/crossfilter.js"></script>
<script type="text/javascript" src="../js/dc.js"></script>
<div class="container">
<script type="text/javascript" src="./header.js"></script>
<p>Scatterplot Matrix Brushing in
dc.js. Imitating <a href="http://bl.ocks.org/mbostock/4063663">Mike's bl.ock</a>.</p>
<p>dc.js will not be as efficient as a custom implementation, and there's a perceptible lag,
but this technique may be useful sometimes. By default, dc.js always waits to trigger events
because it is assumed that updating will be costly
- <span id="wait-verb">add</span> <a id="wait-url">?nowait</a> to see how this
performs <span id="wait-prep">without</span> event delay.</p>
<table id="content"></table>
</div>
<script type="text/javascript">
var fields = ['petal_width', 'petal_length', 'sepal_width', 'sepal_length'];
var rows = ['heading'].concat(fields.slice(0).reverse()),
cols = ['heading'].concat(fields);
if(location.search.indexOf('nowait')!==-1) {
dc.constants.EVENT_DELAY = 0;
d3.select('#wait-verb').text('remove')
d3.select('#wait-prep').text('with');
d3.select('#wait-url').attr('href', location.origin + location.pathname);
} else {
d3.select('#wait-url').attr('href', location.origin + location.pathname + '?nowait');
}
d3.csv('iris.csv', function(error, iris) {
if(error)
throw new Error(error);
iris.forEach(function(d) {
Object.keys(fields).forEach(function(ab) {
d[fields[ab]] = +d[fields[ab]];
});
});
var data = crossfilter(iris);
function make_dimension(var1, var2) {
return data.dimension(function(d) {
return [d[var1], d[var2], d.species];
});
}
function key_part(i) {
return function(kv) {
return kv.key[i];
};
}
var charts = [];
d3.select('#content')
.selectAll('tr').data(rows)
.enter().append('tr').attr('class', function(d) {
return d === 'heading' ? 'heading row' : 'row';
})
.each(function(row, y) {
d3.select(this).selectAll('td').data(cols)
.enter().append('td').attr('class', function(d) {
return d === 'heading' ? 'heading entry' : 'entry';
})
.each(function(col, x) {
var cdiv = d3.select(this).append('div')
if(row === 'heading') {
if(col !== 'heading')
cdiv.text(col.replace('_', ' '))
return;
}
else if(col === 'heading') {
cdiv.text(row.replace('_', ' '))
return;
}
cdiv.attr('class', 'chart-holder');
var chart = dc.scatterPlot(cdiv);
var dim = make_dimension(col,row),
group = dim.group();
var showYAxis = x === 1, showXAxis = y === 4;
chart
.transitionDuration(0)
.width(200 + (showYAxis?25:0))
.height(200 + (showXAxis?20:0))
.margins({
left: showYAxis ? 25 : 8,
top: 5,
right: 0,
bottom: showXAxis ? 20 : 5
})
.dimension(dim).group(group)
.keyAccessor(key_part(0))
.valueAccessor(key_part(1))
.colorAccessor(key_part(2))
.colorDomain(['setosa', 'versicolor', 'virginica'])
.x(d3.scale.linear()).xAxisPadding("0.001%")
.y(d3.scale.linear()).yAxisPadding("0.001%")
.brushOn(true)
.elasticX(true)
.elasticY(true)
.symbolSize(7)
.nonemptyOpacity(0.7)
.emptySize(7)
.emptyColor('#ccc')
.emptyOpacity(0.7)
.excludedSize(7)
.excludedColor('#ccc')
.excludedOpacity(0.7)
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true);
chart.xAxis().ticks(6);
chart.yAxis().ticks(6);
chart.on('postRender', function(chart) {
// remove axes unless at left or bottom
if(!showXAxis)
chart.select('.x.axis').attr('display', 'none');
if(!showYAxis)
chart.select('.y.axis').attr('display', 'none');
// remove clip path, allow dots to display outside
chart.select('.chart-body').attr('clip-path', null);
});
// only filter on one chart at a time
chart.on('filtered', function(_, filter) {
if(!filter)
return;
charts.forEach(function(c) {
if(c !== chart)
c.filter(null);
});
});
charts.push(chart);
});
});
dc.renderAll();
});
</script>
</body>
</html>