mgr/dashboard_v2: improve tooltip of cdSparkline

Added a new scss and class for the tooltip.

Signed-off-by: Tiago Melo <tmelo@suse.com>
This commit is contained in:
Tiago Melo 2018-02-28 17:53:55 +00:00
parent 04a73694d6
commit 986c91f083
5 changed files with 221 additions and 6 deletions

View File

@ -1,10 +1,13 @@
<div class="chart-container"
[ngStyle]="style">
<canvas baseChart
<canvas baseChart #sparkCanvas
[labels]="labels"
[datasets]="datasets"
[options]="options"
[colors]="colors"
[chartType]="'line'">
</canvas>
<div class="chartjs-tooltip" #sparkTooltip>
<table></table>
</div>
</div>

View File

@ -1,4 +1,5 @@
@import '../../../../styles/chart-tooltip.scss';
.chart-container {
position: relative;
margin: auto;
position: static !important;
}

View File

@ -1,12 +1,17 @@
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Component, ElementRef, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
import { Input } from '@angular/core';
import { ChartTooltip } from '../../../shared/models/chart-tooltip';
@Component({
selector: 'cd-sparkline',
templateUrl: './sparkline.component.html',
styleUrls: ['./sparkline.component.scss']
})
export class SparklineComponent implements OnInit, OnChanges {
@ViewChild('sparkCanvas') chartCanvasRef: ElementRef;
@ViewChild('sparkTooltip') chartTooltipRef: ElementRef;
@Input() data: any;
@Input()
style = {
@ -40,7 +45,10 @@ export class SparklineComponent implements OnInit, OnChanges {
}
},
tooltips: {
enabled: true
enabled: false,
mode: 'index',
intersect: false,
custom: undefined
},
scales: {
yAxes: [
@ -66,7 +74,31 @@ export class SparklineComponent implements OnInit, OnChanges {
constructor() {}
ngOnInit() {}
ngOnInit() {
const getStyleTop = (tooltip, positionY) => {
return (tooltip.caretY - tooltip.height - tooltip.yPadding - 5) + 'px';
};
const getStyleLeft = (tooltip, positionX) => {
return positionX + tooltip.caretX + 'px';
};
const chartTooltip = new ChartTooltip(
this.chartCanvasRef,
this.chartTooltipRef,
getStyleLeft,
getStyleTop
);
chartTooltip.customColors = {
backgroundColor: this.colors[0].pointBackgroundColor,
borderColor: this.colors[0].pointBorderColor
};
this.options.tooltips.custom = tooltip => {
chartTooltip.customTooltips(tooltip);
};
}
ngOnChanges(changes: SimpleChanges) {
this.datasets[0].data = changes['data'].currentValue;

View File

@ -0,0 +1,117 @@
import { ElementRef } from '@angular/core';
import * as _ from 'lodash';
export class ChartTooltip {
tooltipEl: any;
chartEl: any;
getStyleLeft: Function;
getStyleTop: Function;
customColors = {
backgroundColor: undefined,
borderColor: undefined
};
checkOffset = false;
/**
* Creates an instance of ChartTooltip.
* @param {ElementRef} chartCanvas Canvas Element
* @param {ElementRef} chartTooltip Tooltip Element
* @param {Function} getStyleLeft Function that calculates the value of Left
* @param {Function} getStyleTop Function that calculates the value of Top
* @memberof ChartTooltip
*/
constructor(
chartCanvas: ElementRef,
chartTooltip: ElementRef,
getStyleLeft: Function,
getStyleTop: Function
) {
this.chartEl = chartCanvas.nativeElement;
this.getStyleLeft = getStyleLeft;
this.getStyleTop = getStyleTop;
this.tooltipEl = chartTooltip.nativeElement;
}
/**
* Implementation of a ChartJS custom tooltip function.
*
* @param {any} tooltip
* @memberof ChartTooltip
*/
customTooltips(tooltip) {
// Hide if no tooltip
if (tooltip.opacity === 0) {
this.tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
this.tooltipEl.classList.remove('above', 'below', 'no-transform');
if (tooltip.yAlign) {
this.tooltipEl.classList.add(tooltip.yAlign);
} else {
this.tooltipEl.classList.add('no-transform');
}
// Set Text
if (tooltip.body) {
const titleLines = tooltip.title || [];
const bodyLines = tooltip.body.map(bodyItem => {
return bodyItem.lines;
});
let innerHtml = '<thead>';
titleLines.forEach(title => {
innerHtml += '<tr><th>' + this.getTitle(title) + '</th></tr>';
});
innerHtml += '</thead><tbody>';
bodyLines.forEach((body, i) => {
const colors = tooltip.labelColors[i];
let style = 'background:' + (this.customColors.backgroundColor || colors.backgroundColor);
style += '; border-color:' + (this.customColors.borderColor || colors.borderColor);
style += '; border-width: 2px';
const span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';
innerHtml += '<tr><td nowrap>' + span + this.getBody(body) + '</td></tr>';
});
innerHtml += '</tbody>';
const tableRoot = this.tooltipEl.querySelector('table');
tableRoot.innerHTML = innerHtml;
}
const positionY = this.chartEl.offsetTop;
const positionX = this.chartEl.offsetLeft;
// Display, position, and set styles for font
if (this.checkOffset) {
const halfWidth = tooltip.width / 2;
this.tooltipEl.classList.remove('transform-left');
this.tooltipEl.classList.remove('transform-right');
if (tooltip.caretX - halfWidth < 0) {
this.tooltipEl.classList.add('transform-left');
} else if (tooltip.caretX + halfWidth > this.chartEl.width) {
this.tooltipEl.classList.add('transform-right');
}
}
this.tooltipEl.style.left = this.getStyleLeft(tooltip, positionX);
this.tooltipEl.style.top = this.getStyleTop(tooltip, positionY);
this.tooltipEl.style.opacity = 1;
this.tooltipEl.style.fontFamily = tooltip._fontFamily;
this.tooltipEl.style.fontSize = tooltip.fontSize;
this.tooltipEl.style.fontStyle = tooltip._fontStyle;
this.tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
}
getBody(body) {
return body;
}
getTitle(title) {
return title;
}
}

View File

@ -0,0 +1,62 @@
.chart-container {
position: absolute;
margin: auto;
cursor: pointer;
overflow: visible;
}
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.chartjs-tooltip {
opacity: 0;
position: absolute;
background: rgba(0, 0, 0, 0.7);
color: white;
border-radius: 3px;
-webkit-transition: all 0.1s ease;
transition: all 0.1s ease;
pointer-events: none;
font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif !important;
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
&.transform-left {
transform: translate(-10%, 0);
&::after {
left: 10%;
}
}
&.transform-right {
transform: translate(-90%, 0);
&::after {
left: 90%;
}
}
}
.chartjs-tooltip::after {
content: ' ';
position: absolute;
top: 100%; /* At the bottom of the tooltip */
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: black transparent transparent transparent;
}
::ng-deep .chartjs-tooltip-key {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 10px;
}