NAME
Quiq::ChartJs::TimeSeries - Erzeuge Zeitreihen-Plot auf Basis von Chart.js
BASE CLASS
SYNOPSIS
Modul laden
use Quiq::ChartJs::TimeSeries;
Objekt instantiieren
my $ch = Quiq::ChartJs::TimeSeries->new(
parameter => 'Windspeed',
unit => 'm/s',
points => \@rows,
pointCallback => sub {
my ($point,$i) = @_;
my ($iso,$val) = split /\t/,$point,2;
return [Quiq::Epoch->new($iso)->epoch*1000,$val];
},
);
HTML-Seite mit Diagramm generieren
my $h = Quiq::Html::Producer->new;
my $html = Quiq::Html::Page->html($h,
title => 'Chart.js testpage',
load => [
js => $ch->cdnUrl('2.8.0'),
],
body => $ch->html($h),
);
Diagramm
(Folgendes Diagramm erscheint nur in HTML - außer auf meta::cpan, da der HTML-Code dort gestrippt wird. Es zeigt 720 Messwerte einer Windgeschwindigkeits-Messung)
DESCRIPTION
Diese Klasse ist ein Perl-Wrapper für die Erzeugung für Zeitreihen-Plots auf Basis von Chart.js. Chart.js ist eine JavaScript-Bibliothek, die Diagramme auf einem HTML5 <canvas> darstellt. Chart.js bietet viele Möglichkeiten der Diagramm-Generierung. Die Einstellungen werden per Datenstruktur an den Chart-Konstruktor übergeben. Die Perl-Klasse ist darauf optimiert, einen speziellen Typ von Diagramm zu erzeugen: einen Zeitreihen-Plot. In einem Zeitreihen-Plot werden die Werte eines Parameters einer bestimmten Einheit (unit) gegen die Zeit geplottet. Die X-Achse ist die Zeitachse und die Y-Achse die Werteachse.
Diagramm-Eigenschaften und wie sie in Chart.js konfiguriert werden
Übergabe der Daten
Zeitreihendaten werden als Array von Punkten übergeben:
data: {
datasets: [{
type: 'line',
data: [__POINTS__],
}],
}
Jeder Punkt in __POINTS__ ist ein JS-Objekt mit der Struktur:
{
t: __JAVASCRIPT_EPOCH__,
y: __VALUE__,
}
Hierbei ist __JAVASCRIPT_EPOCH__ der Zeitpunkt in Unix Epoch mal 1000 (also in Millisekunden-Auflösung).
Diagramm mit konstanter Höhe und variabler Breite
Das <canvas>-Element wird in ein Parent-Element eingebettet, welches die Höhe __HEIGHT__ zugewiesen bekommt:
<div style="height: __HEIGHT__px">
<canvas id="__NAME__"></canvas>
</div>
In den Chart-Optionen wird definiert:
options: {
maintainAspectRatio: false,
}
Damit ist das Diagramm fest auf __HEIGHT__ Pixel Höhe eingestellt, passt sich in der Breite aber dem zur Verfügung stehenden Raum an, auch nach einem Resize.
Konfiguration der Zeitachse
Eine Zeitachse bedarf einiger Konfigurationsarbeit, da die Defaults von Chart.js nicht besonders sinnvoll sind.
options: {
scales: {
xAxes: [{
type: 'time',
ticks: {
minRotation: 30,
maxRotation: 60,
},
time: {
min: __T_MIN__,
max: __T_MAX__,
minUnit: 'second',
displayFormats: {
second: 'YYYY-MM-DD HH:mm:ss',
minute: 'YYYY-MM-DD HH:mm',
hour: 'YYYY-MM-DD HH',
day: 'YYYY-MM-DD',
week: 'YYYY-MM-DD',
month: 'YYYY-MM',
quarter: 'YYYY [Q]Q',
year: 'YYYY',
},
tooltipFormat: 'YYYY-MM-DD HH:mm:ss',
},
}],
},
}
Die X-Achse wird zu einer Zeitachse, wenn
type: 'time'
gesetzt ist.Eine Zeitachse wird speziell über die Unterstruktur
time: ...
konfiguriert.Anders als bei numerischen Achsen werden Minimum und Maximum dort und nicht in der Unterstruktur
ticks: ...
festgelegt.Werden
min:
undmax:
nicht oder aufundefined
gesetzt, werden die Grenzen aus den Daten ermittelt.Die Skalierung ergibt sich aus dem zur Verfügung stehenden Raum. Chart.js entscheidet sich für eine Auflösung aus den 9 Kategorien
millisecond
..year
.Die Tick-Beschriftung für die einzelnen Kategorien wird durch die Substuktur
displayFormats: ...
definiert. Diese sollte komplett durchdefiniert werden, da Defaults von Chart.js nicht besonders sinnvoll sind.Wie die Zeit im Tooltip dargestellt wird, definiert
tooltipFormat:
.Bei längeren Tick-Beschriftungen kann Chart.js diese gekippt darstellen. Da Zeitangaben länger sind, sollte die gekippte Darstellung forciert werden. Die gekippte Darstellung wird forciert, wenn
minRotation:
undmaxRotation
definiert werden. Dann unterbleibt eine gerade Beschriftung, denn ein Wechsel zwischen gerader und gekippter Beschriftung wirkt uneinheitlich.
Raum unter dem Graph einfärben
data: {
datasets: [{
fill: true;
}],
}
Konfigurations-Datenstruktur insgesamt
Die Perl-Klasse übergibt folgende Datenstruktur an den Konstruktor der JavaScript-Klasse Chart, wobei die Platzhalter __XXXX__ ersetzt werden, meist durch den Wert des betreffenden Klassen-Attributs xxxx. Die Liste aller Attribute siehe Abschnitt Attributes.
type: 'line',
data: {
datasets: [{
type: 'line',
lineTension: __LINE_TENSION__,
fill: true,
borderColor: '__LINE_COLOR__',
borderWidth: 1,
pointRadius: __POINT_RADIUS__,
data: [__POINTS__],
}],
},
options: {
maintainAspectRatio: false,
title: {
display: true,
text: '__TITLE__',
fontSize: 16,
fontStyle: 'normal',
},
tooltips: {
intersect: false,
displayColors: false,
backgroundColor: 'rgb(0,0,0,0.6)',
titleMarginBottom: 2,
callbacks: {
label: function(tooltipItem,data) {
return '__PARAMETER__: ' + tooltipItem.value + ' __UNIT__';
},
},
},
legend: {
display: false,
},
scales: {
xAxes: [{
type: 'time',
ticks: {
minRotation: 30,
maxRotation: 60,
},
time: {
min: __T_MIN__,
max: __T_MAX__,
minUnit: 'second',
displayFormats: {
second: 'YYYY-MM-DD HH:mm:ss',
minute: 'YYYY-MM-DD HH:mm',
hour: 'YYYY-MM-DD HH',
day: 'YYYY-MM-DD',
week: 'YYYY-MM-DD',
month: 'YYYY-MM',
quarter: 'YYYY [Q]Q',
year: 'YYYY',
},
tooltipFormat: 'YYYY-MM-DD HH:mm:ss',
},
}],
yAxes: [{
ticks: {
min: __Y_MIN__,
max: __Y_MAX__,
},
scaleLabel: {
display: true,
labelString: '__UNIT__',
},
}],
},
}
SEE ALSO
METHODS
Konstruktor
new() - Instantiiere Objekt
Synopsis
$ch = $class->new(@attVal);
Attributes
- t => \@y (Default: [])
-
Referenz auf Array der Zeit-Werte (in JavaScript-Epoch).
- y => \@y (Default: [])
-
Referenz auf Array der Y-Werte (Weltkoordinaten).
- tMin => $jsEpoch (Default: 'undefined')
-
Kleinster Wert auf der Zeitachse. Der Default 'undefined' bedeutet, dass der Wert aus den Daten ermittelt wird.
- tMax => $jsEpoch (Default: 'undefined')
-
Größter Wert auf der Zeitachse. Der Default 'undefined' bedeutet, dass der Wert aus den Daten ermittelt wird.
- yMin => $val (Default: 'undefined')
-
Kleinster Wert auf der Y-Achse. Der Default 'undefined' bedeutet, dass der Wert aus den Daten ermittelt wird.
- yMax => $val (Default: 'undefined')
-
Größter Wert auf der Y-Achse. Der Default 'undefined' bedeutet, dass der Wert aus den Daten ermittelt wird.
- height => $height (Default: 300)
-
Die Höhe des Diagramms. Eine Breite wird nicht angegeben, diese passt sich dem zur Verfügung stehenden Raum an.
- lineColor => $color (Default: 'rgb(255,0,0,1)')
-
Die Linienfarbe.
- lineTension => $n (Default: 'undefined')
-
"Bezier curve tension of the line." Wenn 0, werden die Punkte gerade verbunden. Der Default 'undefined' bedeutet, dass der von Chart.js voreingestellte Wert 0.4 verwendet wird.
- name => $name (Default: 'plot')
-
Name des Plot. Der Name wird als CSS-Id für die Zeichenfläche (Canvas) und als Variablenname für die Instanz verwendet.
- parameter => $name
-
Der Name des dargestellten Parameters.
- points => \@points (Default: [])
-
Liste der Datenpunkte oder - alternativ - der Elemente, aus denen die Datenpunkte mittels der Methode pointCallback (s.u.) gewonnen werden. Ein Datenpunkt ist ein Array mit zwei numerischen Werten [$x, $y], wobei $x ein JavaScript Epoch-Wert (Unix Epoch in Millisekunden) ist und $y ein beliebiger Y-Wert.
- pointCallback => $sub (Default: undef)
-
Referenz auf eine Subroutine, die fr jedes Element der Liste @points einen Datenpunkt liefert, wie ihn die Klasse erwartet (s.o.). Ist kein rowCallback definiert, werden die Elemente aus @points unverändert verwendet.
- pointRadius => $n (Default: 0)
-
Kennzeichne die Datenpunkte mit einem Kreis des Radius $n. 0 bedeutet, dass die Datenpunkte nicht gekennzeichnet werden.
- showAverage => $bool (Default: 0)
-
Zeige das arithmetische Mittel an.
- showMedian => $bool (Default: 0)
-
Zeige den Median an.
- title => $str (Default: Name des Parameters)
-
Titel, der über das Diagramm geschrieben wird.
- unit => $str
-
Einheit des Parameters. Mit der Einheit wird die Y-Achse beschriftet und sie erscheint im Tooltip.
Returns
Objekt
Description
Instantiiere ein Objekt der Klasse und liefere eine Referenz auf dieses Objekt zurück.
Klassenmethoden
cdnUrl() - Liefere CDN URL
Synopsis
$url = $ch->cdnUrl($version);
Returns
URL (String)
Description
Liefere einen CDN URL für Chart.js in der Version $version.
Objektmethoden
html() - Generiere HTML
Synopsis
$html = $ch->html($h);
Returns
HTML-Code (String)
Description
Liefere den HTML-Code der Chart-Instanz.
js() - Generiere JavaScript
Synopsis
$js = $ch->js;
Returns
JavaScript-Code (String)
Description
Liefere den JavaScript-Code der Chart-Instanz.
IDEAS
minRotation, maxRotation auf einen festen Wert einstellen, z.B. 45, damit alle Diagramme gleich aussehen (?)
Höhe des Diagramms per JS setzen statt im HTML?
JS-Code in Ready-Handler setzen
Tick-Label der Zeitachse berechnen, so dass wiederholende Teile ausgeblendet sind
Zoomen in die Daten. Wie? Plugin?
VERSION
1.222
AUTHOR
Frank Seitz, http://fseitz.de/
COPYRIGHT
Copyright (C) 2024 Frank Seitz
LICENSE
This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.