Commit b1c84bb1 authored by Sascha Herzinger's avatar Sascha Herzinger
Browse files

improved visuals

parent c9a664dd
......@@ -55,6 +55,9 @@
xAxisLabel: 'X Axis Values',
yAxisLabel: 'Y Axis Values',
data: randomBoxplots(),
min: undefined,
max: undefined,
clickCallback: d => console.log(d)
});
}
......
.ac-box-line {
stroke: #888;
stroke-width: 1px;
stroke-width: 2px;
shape-rendering: crispedges;
pointer-events: none;
}
.ac-box-median {
stroke: #888;
stroke: #fff;
stroke-width: 2px;
shape-rendering: crispedges;
pointer-events: none;
}
.ac-box-upper-whisker {
stroke: #888;
stroke-width: 1px;
shape-rendering: crispedges;
}
.ac-box-lower-whisker {
stroke: #888;
stroke-width: 1px;
shape-rendering: crispedges;
}
......@@ -26,6 +25,7 @@
fill: rgb(124, 191, 255);
stroke: none;
shape-rendering: crispedges;
cursor: pointer;
}
.ac-box-axis path {
......@@ -43,4 +43,17 @@
.ac-box-axis .tick text {
font-size: 1.5em;
}
\ No newline at end of file
}
.ac-box-caption {
font-size: 1.25em;
}
.ac-box-label {
font-size: 1em;
}
.ac-box-value {
font-size: 0.6em;
pointer-events: none;
}
......@@ -23,6 +23,23 @@ export default class extends Chart {
this.axisLeft = this.svg
.append('g')
.attr('class', 'ac-box-axis-left ac-box-axis');
this.caption = this.svg
.append('text')
.attr('text-anchor', 'middle')
.attr('class', 'ac-box-caption');
this.xAxisLabel = this.svg
.append('text')
.attr('text-anchor', 'middle')
.style('dominant-baseline', 'central')
.attr('class', 'ac-box-axis-label');
this.yAxisLabel = this.svg
.append('text')
.attr('text-anchor', 'middle')
.style('dominant-baseline', 'central')
.attr('class', 'ac-box-axis-label');
}
static get name() {
......@@ -30,23 +47,39 @@ export default class extends Chart {
}
render({
caption, xAxisLabel, yAxisLabel, data, max, min,
caption, xAxisLabel, yAxisLabel, data, max, min, clickCallback,
}) {
const margin = {
top: this.containerWidth / 10,
right: this.containerWidth / 10,
bottom: this.containerWidth / 10,
left: this.containerWidth / 10,
top: this.containerWidth / 20,
right: this.containerWidth / 20,
bottom: this.containerWidth / 8,
left: this.containerWidth / 8,
};
const width = this.containerWidth - margin.left - margin.right;
const height = this.containerWidth - margin.top - margin.bottom;
const UPPER_LOWER_PADDING = height / 20;
const X_AXIS_LABEL_SPACE = margin.bottom / 4;
const Y_AXIS_LABEL_SPACE = margin.left / 4;
this.caption
.text(caption)
.attr('transform', `translate(${width / 2}, ${-margin.top / 2})`);
this.xAxisLabel
.text(xAxisLabel)
.attr('transform', `translate(${width / 2}, ${height + margin.bottom - X_AXIS_LABEL_SPACE / 2})`);
this.yAxisLabel
.text(yAxisLabel)
.attr('transform', `translate(${-margin.left + Y_AXIS_LABEL_SPACE / 2}, ${height / 2})rotate(-90)`);
const groups = data.map(d => d.group);
const color = d3.scaleOrdinal()
.domain(groups)
.range(d3.schemePastel1);
.range(d3.schemeSet2);
const x = d3.scaleBand()
.domain(groups)
......@@ -70,8 +103,6 @@ export default class extends Chart {
return d3.min(minLowerWhisker, min);
})();
const UPPER_LOWER_PADDING = height / 20;
const y = d3.scaleLinear()
.domain([minValue, maxValue])
.range([height - UPPER_LOWER_PADDING, UPPER_LOWER_PADDING]);
......@@ -89,14 +120,14 @@ export default class extends Chart {
.attr('transform', 'rotate(45)')
.attr('text-anchor', 'start')
.attr('x', 8)
.call(textUtils.axisShrinkFitText, margin.bottom);
.call(textUtils.axisShrinkFitText, margin.bottom - X_AXIS_LABEL_SPACE);
this.axisRight
.attr('transform', `translate(${width}, 0)`)
.call(axisRight);
this.axisLeft
.call(axisLeft)
.selectAll('text')
.call(textUtils.axisShrinkFitText, margin.left);
.call(textUtils.axisShrinkFitText, margin.left - Y_AXIS_LABEL_SPACE);
d3.select(this.container).select('svg')
.attr('width', width + margin.left + margin.right)
......@@ -114,6 +145,21 @@ export default class extends Chart {
.attr('y', d => y(d.median))
.attr('width', x.bandwidth())
.style('fill', d => color(d.group))
.style('opacity', 1)
.on('mouseenter', (d) => {
this.svg.selectAll('.ac-box-value')
.filter(e => e.group === d.group)
.transition()
.duration(500)
.style('opacity', 1);
})
.on('mouseleave', () => {
this.svg.selectAll('.ac-box-value')
.transition()
.duration(500)
.style('opacity', 0);
})
.on('click', d => clickCallback(d))
.transition()
.duration(500)
.attr('y', d => y(d.upperQuartile))
......@@ -126,6 +172,7 @@ export default class extends Chart {
.attr('y', d => y(d.upperQuartile))
.attr('width', x.bandwidth())
.attr('height', d => y(d.lowerQuartile) - y(d.upperQuartile))
.style('opacity', 1)
.style('fill', d => color(d.group));
box.exit()
......@@ -137,6 +184,7 @@ export default class extends Chart {
line.enter()
.append('line')
.attr('class', 'ac-box-line')
.attr('stroke', d => color(d.group))
.attr('x1', d => x(d.group) + x.bandwidth() / 2)
.attr('y1', d => y(d.median))
.attr('x2', d => x(d.group) + x.bandwidth() / 2)
......@@ -149,6 +197,7 @@ export default class extends Chart {
line
.transition()
.duration(500)
.attr('stroke', d => color(d.group))
.attr('x1', d => x(d.group) + x.bandwidth() / 2)
.attr('y1', d => y(d.upperWhisker))
.attr('x2', d => x(d.group) + x.bandwidth() / 2)
......@@ -157,57 +206,57 @@ export default class extends Chart {
line.exit()
.remove();
const upperWhisker = this.svg.selectAll('.ac-box-upper-whisker')
.data(data);
upperWhisker.enter()
.append('line')
.attr('class', 'ac-box-upper-whisker')
.attr('x1', d => x(d.group) + x.bandwidth() / 3)
.attr('y1', d => y(d.median))
.attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
.attr('y2', d => y(d.median))
.transition()
.duration(500)
.attr('y1', d => y(d.upperWhisker))
.attr('y2', d => y(d.upperWhisker));
upperWhisker
.transition()
.duration(500)
.attr('x1', d => x(d.group) + x.bandwidth() / 3)
.attr('y1', d => y(d.upperWhisker))
.attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
.attr('y2', d => y(d.upperWhisker));
upperWhisker.exit()
.remove();
const lowerWhisker = this.svg.selectAll('.ac-box-lower-whisker')
.data(data);
lowerWhisker.enter()
.append('line')
.attr('class', 'ac-box-lower-whisker')
.attr('x1', d => x(d.group) + x.bandwidth() / 3)
.attr('y1', d => y(d.median))
.attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
.attr('y2', d => y(d.median))
.transition()
.duration(500)
.attr('y1', d => y(d.lowerWhisker))
.attr('y2', d => y(d.lowerWhisker));
lowerWhisker
.transition()
.duration(500)
.attr('x1', d => x(d.group) + x.bandwidth() / 3)
.attr('y1', d => y(d.lowerWhisker))
.attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
.attr('y2', d => y(d.lowerWhisker));
lowerWhisker.exit()
.remove();
// const upperWhisker = this.svg.selectAll('.ac-box-upper-whisker')
// .data(data);
//
// upperWhisker.enter()
// .append('line')
// .attr('class', 'ac-box-upper-whisker')
// .attr('x1', d => x(d.group) + x.bandwidth() / 3)
// .attr('y1', d => y(d.median))
// .attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
// .attr('y2', d => y(d.median))
// .transition()
// .duration(500)
// .attr('y1', d => y(d.upperWhisker))
// .attr('y2', d => y(d.upperWhisker));
//
// upperWhisker
// .transition()
// .duration(500)
// .attr('x1', d => x(d.group) + x.bandwidth() / 3)
// .attr('y1', d => y(d.upperWhisker))
// .attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
// .attr('y2', d => y(d.upperWhisker));
//
// upperWhisker.exit()
// .remove();
//
// const lowerWhisker = this.svg.selectAll('.ac-box-lower-whisker')
// .data(data);
//
// lowerWhisker.enter()
// .append('line')
// .attr('class', 'ac-box-lower-whisker')
// .attr('x1', d => x(d.group) + x.bandwidth() / 3)
// .attr('y1', d => y(d.median))
// .attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
// .attr('y2', d => y(d.median))
// .transition()
// .duration(500)
// .attr('y1', d => y(d.lowerWhisker))
// .attr('y2', d => y(d.lowerWhisker));
//
// lowerWhisker
// .transition()
// .duration(500)
// .attr('x1', d => x(d.group) + x.bandwidth() / 3)
// .attr('y1', d => y(d.lowerWhisker))
// .attr('x2', d => x(d.group) + x.bandwidth() - x.bandwidth() / 3)
// .attr('y2', d => y(d.lowerWhisker));
//
// lowerWhisker.exit()
// .remove();
const median = this.svg.selectAll('.ac-box-median')
.data(data);
......@@ -230,5 +279,85 @@ export default class extends Chart {
median.exit()
.remove();
const upperWhiskerValue = this.svg.selectAll('.ac-box-value-upper-whisker')
.data(data);
upperWhiskerValue.enter()
.append('text')
.attr('class', 'ac-box-value ac-box-value-upper-whisker')
.merge(upperWhiskerValue)
.attr('transform', d => `translate(${x(d.group) + x.bandwidth() - x.bandwidth() / 3}, ${y(d.upperWhisker)})`)
.attr('text-anchor', 'start')
.style('dominant-baseline', 'central')
.style('opacity', 0)
.text(d => d.upperWhisker);
upperWhiskerValue.exit()
.remove();
const lowerWhiskerValue = this.svg.selectAll('.ac-box-value-lower-whisker')
.data(data);
lowerWhiskerValue.enter()
.append('text')
.attr('class', 'ac-box-value ac-box-value-lower-whisker')
.merge(lowerWhiskerValue)
.attr('transform', d => `translate(${x(d.group) + x.bandwidth() - x.bandwidth() / 3}, ${y(d.lowerWhisker)})`)
.attr('text-anchor', 'start')
.style('dominant-baseline', 'central')
.style('opacity', 0)
.text(d => d.lowerWhisker);
lowerWhiskerValue.exit()
.remove();
const upperQuartileValue = this.svg.selectAll('.ac-box-value-upper-quartile')
.data(data);
upperQuartileValue.enter()
.append('text')
.attr('class', 'ac-box-value ac-box-value-upper-quartile')
.merge(upperQuartileValue)
.attr('transform', d => `translate(${x(d.group)}, ${y(d.upperQuartile)})`)
.attr('text-anchor', 'end')
.style('dominant-baseline', 'central')
.style('opacity', 0)
.text(d => d.upperQuartile);
upperQuartileValue.exit()
.remove();
const lowerQuartileValue = this.svg.selectAll('.ac-box-value-lower-quartile')
.data(data);
lowerQuartileValue.enter()
.append('text')
.attr('class', 'ac-box-value ac-box-value-lower-quartile')
.merge(lowerQuartileValue)
.attr('transform', d => `translate(${x(d.group)}, ${y(d.lowerQuartile)})`)
.attr('text-anchor', 'end')
.style('dominant-baseline', 'central')
.style('opacity', 0)
.text(d => d.lowerQuartile);
lowerQuartileValue.exit()
.remove();
const medianValue = this.svg.selectAll('.ac-box-value-median')
.data(data);
medianValue.enter()
.append('text')
.attr('class', 'ac-box-value ac-box-value-median')
.merge(medianValue)
.attr('transform', d => `translate(${x(d.group) + x.bandwidth()}, ${y(d.median)})`)
.attr('text-anchor', 'start')
.style('dominant-baseline', 'central')
.style('opacity', 0)
.text(d => d.median);
medianValue.exit()
.remove();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment