zeus.ugent.be/content/assets/scripts/datavis/rankingChart.js
2018-05-16 22:42:07 +02:00

117 lines
3.6 KiB
JavaScript

(function() {
function rankingChart() {
var margin = { top: 50, right: 120, bottom: 20, left: 120 };
var data;
var updateData;
function chart(svg) {
let width = $(svg.node()).width();
let height = svg.attr('height');
width -= margin.left + margin.right;
height -= margin.top + margin.bottom;
const g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
updateData = function () {
let allDates = _(d3.entries(data).map(e => e.value)).flatten().value().map(e => e.time);
let allIdx = _(d3.entries(data).map(e => e.value)).flatten().value().map(e => e.idx);
const x = d3.scaleTime()
.domain(d3.extent(allDates))
.range([0, width])
.nice()
;
let axis = d3.axisTop(x);
g.append('g')
.attr('transform', `translate(0, -20)`)
.call(axis);
const y = d3.scaleLinear()
.domain([0, d3.max(allIdx)])
.range([0, height])
;
const c = d3.scaleOrdinal(d3.schemeCategory10);
const line = d3.line()
.x(d => x(d.time))
.y(d => y(d.idx))
.curve(d3.curveMonotoneX)
;
const minTimes = d3.entries(data).map(e => _(e.value).minBy('time'));
const maxTimes = d3.entries(data).map(e => _(e.value).maxBy('time'));
function mouseover(ident) {
return function inner(d, i, sel) {
const path = g.selectAll('path.rankPath').filter(e => d[ident] === e.key);
const others = g.selectAll('path.rankPath').filter(e => d[ident] !== e.key);
path.attr('stroke-width', 6);
others.attr('stroke', 'gray');
}
}
function mouseout(ident) {
return function inner(d, i, sel) {
const path = g.selectAll('path.rankPath').filter(e => d[ident] === e.key);
const others = g.selectAll('path.rankPath');
path.attr('stroke-width', 3);
others.attr('stroke', (_, i) => c(i));
}
}
g.selectAll('path.rankPath').data(d3.entries(data)).enter().append('path')
.classed('rankPath', true)
.attr('fill-opacity', 0)
.attr('stroke', (_, i) => c(i))
.attr('stroke-width', 3)
.attr('d', d => {
const lastVal = d.value[d.value.length - 1];
const nVal = {...lastVal, time: x.domain()[1]}
return line(d.value.concat([nVal]));
})
.on('mouseover', mouseover('key'))
.on('mouseout', mouseout('key'))
;
g.selectAll('text.begin').data(minTimes).enter().append('text')
.classed('begin', true)
.attr('x', d => x(d.time) - 5)
.attr('y', d => y(d.idx) + 4)
.attr('text-anchor', 'end')
.text(d => d.name)
.on('mouseover', mouseover('name'))
.on('mouseout', mouseout('name'))
;
g.selectAll('text.end').data(maxTimes).enter().append('text')
.classed('end', true)
.attr('x', d => x.range()[1] + 5)
.attr('y', d => y(d.idx) + 4)
.attr('text-anchor', 'begin')
.text(d => d.name)
.on('mouseover', mouseover('name'))
.on('mouseout', mouseout('name'))
;
}
updateData();
}
chart.data = function (value) {
if (!arguments.length) return data;
data = value;
if (typeof updateData === 'function') updateData();
return chart;
}
return chart;
}
window['rankingChart'] = rankingChart;
})();