dc
Version:
A multi-dimensional charting library built to work natively with crossfilter and rendered using d3.js
204 lines (194 loc) • 8.57 kB
HTML
<html lang="en">
<head>
<title>dc.js - Align Y Axes Example</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;
}
#hscroll {
width: 100%;
overflow: scroll;
padding-left: 20px;
}
#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;
}
</style>
</head>
<body>
<script type="text/javascript" src="../js/promise-polyfill.js"></script>
<script type="text/javascript" src="../js/fetch.umd.js"></script>
<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>This page demonstrates the
<a href="https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.compositeChart+alignYAxes">compositeChart.alignYAxes</a>
feature on different combinations of negative and positive data. <code>alignYAxes</code> is only valid if both child charts have
<a href="https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.coordinateGridMixin+elasticY"><code>elasticY</code></a>.
The left zero point will be horizontal with the right zero point, and the heights of the two series will be equal.
(As with <code>elasticY</code>, height is currently measured from the y=0 line - see <a href="https://github.com/dc-js/dc.js/issues/667">#667</a>.)</p>
</div>
<div id="hscroll">
<table id="content"></table>
</div>
<script type="text/javascript">
var posiness = ['heading', 'above', 'upward', 'even', 'downward', 'below'];
var N = 20;
var gen = d3.randomNormal();
function distribute(vals, min, max) {
var ext = d3.extent(vals);
return vals.map(function(x) {
return min + (x-ext[0]) * (max-min)
/ (ext[1]-ext[0]);
});
}
function distribution(posi, scale) {
var vals = d3.range(N).map(gen);
switch(posi) {
case 'above': return distribute(vals, scale*0.2, scale*1.2);
case 'upward': return distribute(vals, -scale*0.1, scale*0.9);
case 'even': return distribute(vals, -scale*0.5, scale*0.5);
case 'downward': return distribute(vals, -scale*0.9, scale*0.1);
case 'below': return distribute(vals, -scale*1.2, -0.2);
default: throw 'no';
}
}
function dataset(lposi, rposi) {
var ldist = distribution(lposi, 10),
rdist = distribution(rposi, 100);
return ldist.map(function(v, i) { return {key: i, lvalue: v, rvalue: rdist[i]}; });
}
var line = d3.line()
.curve(d3.curveLinear);
function draw_horizontals(chart, hz) {
chart.g().select('g.chart-body')
.selectAll('path.horizontal').data(hz).enter()
.append('path').attr('class', function(d) { return d.classes.concat(['horizontal']).join(' '); })
.attr('d', function(d) {
var y = chart.y()(d.y);
return line([[chart.x().range()[0], y], [chart.x().range()[1], y]]);
});
}
var get_value = dc.pluck('value');
function init() {
d3.select('#content')
.selectAll('tr').data(posiness)
.enter().append('tr').attr('class', function(d) {
return d === 'heading' ? 'heading row' : 'row';
})
.each(function(rposi) {
d3.select(this).selectAll('td').data(posiness)
.enter().append('td').attr('class', function(d) {
return d === 'heading' ? 'heading entry' : 'entry';
})
.each(function(lposi) {
var cdiv = d3.select(this).append('div')
if(lposi === 'heading') {
if(rposi !== 'heading')
cdiv.text('right ' + rposi)
return;
}
else if(rposi === 'heading') {
cdiv.text('left ' + lposi)
return;
}
cdiv.attr('class', 'chart-holder');
var chart = dc.compositeChart(cdiv);
var ndx = crossfilter(dataset(lposi, rposi)),
dim = ndx.dimension(function(d) { return d.key; }),
lgroup = dim.group().reduceSum(function(d) { return d.lvalue; }),
rgroup = dim.group().reduceSum(function(d) { return d.rvalue; });
chart
.width(200)
.height(200)
.margins({left: 25, top: 20, right: 30, bottom: 20})
.x(d3.scaleLinear())
.brushOn(false)
.alignYAxes(true)
.elasticX(true)
.elasticY(true)
.compose([
dc.lineChart(chart)
.dimension(dim)
.group(lgroup)
.x(d3.scaleLinear())
.yAxisPadding(1)
.on('pretransition', function(chart) {
draw_horizontals(chart, [
{classes: ['left','zero'], y: 0},
{classes: ['left','extreme'], y: d3.min(lgroup.all(), get_value)},
{classes: ['left','extreme'], y: d3.max(lgroup.all(), get_value)}
]);
}),
dc.lineChart(chart)
.dimension(dim)
.group(rgroup)
.x(d3.scaleLinear())
.ordinalColors(["darkorange"])
.yAxisPadding(10)
.useRightYAxis(true)
.on('pretransition', function(chart) {
draw_horizontals(chart, [
{classes: ['right','zero'], y: 0},
{classes: ['right','extreme'], y: d3.min(rgroup.all(), get_value)},
{classes: ['right','extreme'], y: d3.max(rgroup.all(), get_value)}
]);
})
]);
});
});
}
init();
dc.renderAll();
</script>
</body>
</html>