NAME

Quiq::ChartJs::TimeSeries - Erzeuge Zeitreihen-Plot auf Basis von Chart.js

BASE CLASS

Quiq::Hash

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 auf HTML-Seiten, es zeigt 720 Messwerte einer Windgeschwindigkeits-Messung)

DESCRIPTION

Erzeuge einen Zeitreihen-Plot auf Basis von Chart.js. Chart.js ist eine JavaScript-Bibliothek zur Darstellung von Diagrammen auf einem HTML5 <canvas>. Chart.js bietet viele Möglichkeiten der Diagramm-Generierung. Die Einstellungen werden per Datenstruktur an den Konstruktor übergeben. Diese Perl-Klasse ist darauf optimiert, einen speziellen Typ von Diagramm zu erzeugen: Zeitreihen-Plots.

Diagramm-Eigenschaften und wie sie konfiguriert werden

Übergabe der Daten

Zeitreihendaten werden als Array von Punkten übergeben:

data: {
    datasets: [{
        type: 'line',
        data: [__POINTS__],
    }],
}

Jeder Punkt in __POINTS__ ist ein 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 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 besitzt die Unterstruktur time: ....

  • Anders als bei numerischen Achsen werden Minimum und Maximum dort und nicht in der Unterstruktur ticks: ... festgelegt.

  • Werden min: und max: nicht oder auf undefined 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: und maxRotation 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

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 voreingestellte Wert von Chart.js 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.

title => $str (Default: Name des Parameters)

Titel, der über das Diagramm geschrieben wird.

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.

unit => $str

Einheit des Parameters. Mit der Einheit wird die Y-Achse beschriftet und sie erscheint im Tooltip.

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.

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);
$html = $class->html($h,@attVal);

Returns

HTML-Code (String)

Description

Liefere den HTML-Code der Chart-Instanz.

VERSION

1.166

AUTHOR

Frank Seitz, http://fseitz.de/

COPYRIGHT

Copyright (C) 2019 Frank Seitz

LICENSE

This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.