|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
|
|
</head> |
|
<body> |
|
|
|
<div id="chart"></div> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> |
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> |
|
|
|
|
|
<script> |
|
|
|
// create one interval brush for each histogram |
|
const brushDelay = vl.selectInterval('delay').encodings('x'); |
|
const brushDist = vl.selectInterval('dist').encodings('x'); |
|
const brushTime = vl.selectInterval('time').encodings('x'); |
|
|
|
// function that creates a histogram visualization |
|
function hist(field, brush, crossfilter) { |
|
// binned x-axis encoding |
|
const x = vl.x() |
|
.fieldQ(field) |
|
.bin({maxbins: 100, minstep: 1}) |
|
.axis({title: field, titleAnchor: 'start', format: 'd'}); |
|
|
|
return vl.layer( |
|
// transparent base layer with unfiltered data |
|
vl.markBar().select(brush) |
|
.encode(x, vl.color().value('transparent')), |
|
// cross-filtered histogram bars |
|
vl.markBar().transform(vl.filter(crossfilter)) |
|
.encode(x, vl.y().count().axis(null)) |
|
) |
|
.width(900) |
|
.height(100); |
|
} |
|
|
|
// vconcat three cross-filtered histograms |
|
const chartSpec = vl.vconcat( |
|
hist('delay', brushDelay, vl.and(brushDist, brushTime)), |
|
hist('distance', brushDist, vl.and(brushDelay, brushTime)), |
|
hist('time', brushTime, vl.and(brushDelay, brushDist)) |
|
) |
|
.data('https://cdn.jsdelivr.net/npm/vega-datasets@1/data/flights-5k.json') |
|
.transform(vl.calculate('hours(datum.date) + minutes(datum.date) / 60').as('time')) |
|
.config({view: {stroke: null}}) |
|
.toJSON(); |
|
|
|
vegaEmbed("#chart", chartSpec); |
|
</script> |
|
|
|
</body> |
|
</html> |