atlas-guide
Version:
Atlas is living style-guides & pattern library static site generator with extensive CSS monitoring and components info that could be used virtually with any scss/css project
156 lines (128 loc) • 4.68 kB
JavaScript
;
(function() {
// chat scroll + rounded line
// animation
function LineChart(rawNode) {
this.instance = rawNode;
this.chartData = undefined;
this.getData();
this.initChart();
}
LineChart.prototype.getData = function () {
let data = this.instance.querySelector('defs').getAttribute('data-chart');
try {
data = JSON.parse(data);
if (!data.length) {
return;
}
} catch (e) {
console.log(e);
}
this.chartData = data;
};
LineChart.prototype.initChart = function() {
const d3 = window.d3;
const margin = {top: 20, right: 0, bottom: 10, left: 20};
const width = document.querySelector('.atlas-stat-sheet').offsetWidth;
const height = 400;
const svg = d3.select(this.instance);
const data = this.chartData;
if (!data) {
return;
}
// Cache basic statistics
const dataArray = data.map(d => d.data).sort();
const max = d3.max(dataArray);
const mean = d3.mean(dataArray);
//const iqtl = d3.quantile(dataArray, 0.25);
//const iiiqtl = d3.quantile(dataArray, 0.75);
const scaleX = d3.scaleLinear()
.domain([0, data.length])
.range([0, width]);
const scaleY = d3.scaleLinear()
.domain([0, max])
.range([height, 0]);
const area = d3.area()
.x((d, i) => scaleX(i))
.y0(height)
.y1(d => scaleY(d.data));
const line = d3.line()
.x((d, i) => scaleX(i))
.y(d => scaleY(d.data));
// DOM
svg.attr('viewBox', '0 0 ' +
(width + margin.left + margin.right) + ' ' +
(height + margin.top + margin.bottom));
const inner = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// Axis
inner.append('g')
.call(d3.axisLeft(scaleY)
.ticks(3)
.tickValues([0, 10, 20, 30, 100, mean, max])
.tickSize(-width, 0, 0))
.select('.domain')
.remove();
inner.selectAll('g.tick')
.filter(d => d === mean)
.attr('class', 'tick mean');
inner.append('path')
.data([data])
.attr('fill', 'grey')
.attr('stroke', 'steelblue')
.attr('class', 'area')
.attr('d', area);
inner.append('path')
.data([data])
.attr('fill', 'none')
.attr('class', 'area-line')
.attr('stroke', 'blue')
.attr('stroke-width', 1)
.attr('d', line);
// Mark huge charts
if (data.length > 600) {
inner.select('.area-line').attr('class', 'area-line _huge');
inner.select('.area').attr('class', 'area _huge');
}
// Tooltip
const focus = inner.append('g')
.attr('class', 'focus');
focus.append('rect')
.attr('width', 1)
.attr('height', height)
.attr('style', 'opacity: 0.1')
.attr('fill', 'black');
focus.append('text')
.attr('y', -10);
const focusInner = focus.append('g')
.attr('class', 'focus-line');
focusInner.append('circle')
.attr('r', 3)
.attr('fill', 'black');
svg.on('mousemove', function () {
const mouseX = d3.mouse(this)[0] - margin.left - margin.right;
const itemIndex = Math.round(scaleX.invert(mouseX));
if (itemIndex > data.length - 1 || itemIndex < 0) {
return;
}
const itemSpecificity = data[itemIndex].data;
const itemSelector = data[itemIndex].selector;
focus.attr('transform', 'translate(' + scaleX(itemIndex) + ',0)');
focusInner.attr('transform', 'translate(' + 0 + ',' + scaleY(itemSpecificity) + ')');
if (mouseX > width * 0.6) {
focus.select('text')
.attr('text-anchor', 'end')
.attr('x', 8)
.text(itemSpecificity + ' ' + itemSelector);
} else {
focus.select('text')
.attr('text-anchor', 'start')
.attr('x', -8)
.text(itemSpecificity + ' ' + itemSelector);
}
});
};
document.querySelectorAll('.js-line-chart').forEach(
item => new LineChart(item)
);
}());