Stagger line chart annotations when they are too close

This commit is contained in:
Michael Lange
2020-08-03 19:48:36 -07:00
parent 2868d3e7fb
commit 4936c3f658
5 changed files with 37 additions and 4 deletions

View File

@@ -290,15 +290,25 @@ export default class LineChart extends Component.extend(WindowResizable) {
sortedAnnotations = sortedAnnotations.reverse();
}
let prevX = 0;
let prevHigh = false;
return sortedAnnotations.map(annotation => {
const x = xScale(annotation[xProp]);
const y = 0; // TODO: prevent overlap by staggering y-offset
if (prevX && !prevHigh && Math.abs(x - prevX) < 30) {
prevHigh = true;
} else if (prevHigh) {
prevHigh = false;
}
const y = prevHigh ? -15 : 0;
const formattedX = this.xFormat(timeseries)(annotation[xProp]);
prevX = x;
return {
annotation,
style: `transform:translate(${x}px,${y}px)`,
icon: iconFor[annotation.type],
iconClass: iconClassFor[annotation.type],
staggerClass: prevHigh ? 'is-staggered' : '',
label: `${annotation.type} event at ${formattedX}`,
};
});

View File

@@ -2,6 +2,10 @@
position: absolute;
height: 100%;
&.is-staggered {
height: calc(100% + 15px);
}
.indicator {
color: $grey;
display: block;

View File

@@ -4,7 +4,7 @@
position: relative;
&.with-annotations {
margin-top: 1.5em;
margin-top: 2em;
}
& > svg {

View File

@@ -28,7 +28,7 @@
</svg>
<div data-test-annotations class="line-chart-annotations" style={{this.chartAnnotationsStyle}}>
{{#each this.processedAnnotations as |annotation|}}
<div data-test-annotation class="chart-annotation {{annotation.iconClass}}" style={{annotation.style}}>
<div data-test-annotation class="chart-annotation {{annotation.iconClass}} {{annotation.staggerClass}}" style={{annotation.style}}>
<button
type="button"
class="indicator"

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -159,7 +159,19 @@ export let Annotations = () => {
@data={{this.data}}
@annotations={{this.annotations}}
@onAnnotationClick={{action (mut this.activeAnnotation)}}/>
<p>{{this.activeAnnotation.info}}</p>
{{/if}}
</div>
<p style="margin:2em 0; padding: 1em; background:#FFEEAC">{{this.activeAnnotation.info}}</p>
<h5 class="title is-5">Line Chart data with staggered annotations</h5>
<div class="block" style="height:150px; width:450px">
{{#if (and this.data this.annotations)}}
<LineChart
@timeseries={{true}}
@xProp="x"
@yProp="y"
@data={{this.data}}
@annotations={{this.annotations}}
@onAnnotationClick={{action (mut this.activeAnnotation)}}/>
{{/if}}
</div>
`,
@@ -192,6 +204,13 @@ export let Annotations = () => {
type: 'info',
info: 'This is the end of the first period',
},
{
x: moment()
.add(96, 'd')
.toDate(),
type: 'info',
info: 'A close annotation for staggering purposes',
},
{
x: moment()
.add((90 / 4) * 3, 'd')