The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Quiq::PlotlyJs::XY::DiagramGroup - Gruppe von XY-Diagrammen

BASE CLASS

Quiq::Hash

DESCRIPTION

Diese Klasse ist ein Perl-Wrapper für die Erzeugung einer Gruppe von XY-Diagrammen auf Basis von Plotly.js, Beispiel siehe Plotly.js: Plotten und analysieren einer Gruppe von Zeitreihen.

Die Diagrammgruppe zeichnet sich dadurch aus, dass durch alle Plots der Gruppe synchron gescrollt werden kann. In dem Diagramm, dessen Rangeslider aktiviert ist, kann mit der linken Maustaste im Plot ein Zeitbereich ausgewählt und anschließend mit dem Rangeslider durch den Gesamtbereich gescrollt werden. Das Zoomen und Scrollen findet dabei über allen Diagrammen synchron statt. Bei Doppelklick in den Plot-Breich wird der ursprüngliche Zustand wieder hergestellt. Beim Überfahren der Plots mit der Maus wird das Koordinatenpaar des nächstgelegenen Punktes angezeigt. Über das Menü "Shape" kann die Kurvenform eingestellt und mittels des Buttons "Download as PNG" der aktuelle Diagramm-Zustand als Grafik heruntergeladen werden.

Es gibt zwei Möglichkeiten, die Plot-Daten in die Diagramme zu übertragen:

  1. Die Arrays x, y (und ggf. z) werden dem Parameter-Objekt direkt mitgegeben.

  2. Die Arrays x, y (und ggf. z) werden per Ajax-Aufruf besorgt, wenn beim Parameter-Objekt ein URL definiert ist. In diesem Fall sind die Daten sind nicht Teil der Seite, sondern werden per asynchronem Ajax-Request (ggf. via Cross-Origin Resource Sharing) geladen.

Das Laden per Ajax-Request hat den Vorteil, dass das Holen der Daten parallel geschieht während die Diagramme auf der Seite schon (leer) angezeigt werden, d.h. der Seitenaufbau ist schneller und die Daten werden performanter besorgt.

Parameter-Objekte

Bei der Instantiierung des DiagramGroup-Objekts wird dem Konstruktor eine Liste von Parameter-Objekten übergeben. Jeder Parameter wird in ein Diagramm geplottet. Folgende Information wird für die Darstellung des Diagramms ohne Daten benötigt:

  • Name (des Parameters)

  • Einheit

  • Farbe

  • Kleinster Wert der X-Achse

  • Größter Wert der X-Achse

  • Kleinster Wert der Y-Achse

  • Größter Wert der Y-Achse

Die Daten selbst werden entweder als Arrays x, y (und ggf. z) übergeben oder, was vorzuziehen ist, per asynchronem Ajax-Aufruf geladen, via url.

Beispiel für eine Vorab-Selektion der grundlegenden Diagramm-Daten:

  my $parT = $db->select(qq~
      SELECT
          par_id
          , par_name
          , par_unit
          , par_ymin
          , par_ymax
          , par_color
          , MIN(val_time) AS par_time_min
          , MAX(val_time) AS par_time_max
          , COALESCE(MIN(val_value), par_ymin, 0) AS par_value_min
          , COALESCE(MAX(val_value), par_ymax, 1) AS par_value_max
      FROM
          parameter AS par
          LEFT JOIN value AS val
              ON par_id = val_parameter_id
                  AND val_time >= '__BEGIN__'
                  AND val_time < '__END__'
      WHERE
          par_station_id = __STA_ID__
          AND par_name IN (__PARAMETERS__)
      GROUP BY
          par_id
          , par_name
          , par_unit
          , par_ymin
          , par_ymax
          , par_color
      ~,
      -placeholders =>
          __STA_ID__ => $sta->sta_id,
          __PARAMETERS__ => !@parameters? "''":
              join(', ',map {"'$_'"} @parameters),
          __BEGIN__ => $begin,
          __END__ => $end,
  );
  $parT->normalizeNumber('par_ymin','par_ymax','par_value_min',
      'par_value_max');
  my %parI = $parT->index('par_name');

Vorgegeben ist die Menge der Parameter @parameters und der Zeitbereich $begin und $end.

Die Instantiierung eines Parameters:

  push @par,Quiq::PlotlyJs::XY::Diagram->new(
      title => $par_name,
      yTitle => Encode::decode('utf-8',$par->par_unit),
      color => '#'.$par->par_color,
      # x => scalar($valT->values('val_time')),
      xMin => $begin, # $par->par_time_min,
      xMax => $end, # $par->par_time_max,
      # y => scalar($valT->values('val_value')),
      yMin => $par_value_min,
      yMax => $par_value_max,
      url => 'http://s31tz.de/timeseries?'.Quiq::Url->queryEncode(
          name => $par->par_name,
      ),
      # z => scalar($valT->values('qua_color')),
      zName => 'Quality',
  );

Die Daten werden per Ajax geladen. Format der text/plain-Antwort:

  2009-02-19 00:00:00<TAB>1025.2<TAB>#0000ff
  ...

Aufbau HTML

Der HTML-Code der Diagrammgruppe hat folgenden Aufbau. Hierbei ist NAME der Name der Diagrammgruppe, die beim Konstruktor angegeben wird, und N die laufende Nummer des Diagramms, beginnend mit 1.

  <div id="NAME" class="diagramGroup">
    <table ...>
    <tr>
      <td id="NAME-dN" class="diagram" ...></td>
    </tr>
    <tr>
      <td>
        ...
        Rangeslider: <input type="checkbox" id="NAME-rN" class="rangeslider" ... />
        Shape: <select id="NAME-sN" ...>...
      </td>
    </tr>
    </table>
    ...
  </div>

Über die Id kann das jeweilige DOM-Objekt von CSS/JavaScript aus eindeutig adressiert werden, über die Klasse die Menge der gleichartigen DOM-Objekte.

id="NAME"

Id der Diagrammgruppe.

class="diagramGroup"

Klasse aller Diagrammgruppen.

id="NAME-dN"

Id des Nten Diagramms der Diagrammgruppe.

class="diagram"

Klasse aller Diagramme.

id="NAME-rN"

Id der Nten Rangeslider-Checkbox.

class="rangeslider"

Klasse aller Rangeslider.

METHODS

Konstruktor

new() - Instantiiere Objekt

Synopsis

  $dgr = $class->new(@attVal);

Attributes

debug => $bool (Default: 0)

Zeige über dem Diagramm die Formatierungsgrößen an, die bei unterschiedlicher Höhe oder Fontgröße angepasst werden müssen.

diagrams => \@diagrams

Liste der Diagramm-Objekte. Die Diagramm-Objekte sind vom Typ Quiq::PlotlyJs::XY::Diagram und definieren die Metadaten für die einzelnen Diagramme der Diagramm-Gruppe.

downloadPng => $bool (Default: 1)

Biete einen Button zum Herunterladen der Diagramm-Grafik an.

fillArea => $bool (Default: 1)

Biete eine Checkbox zum An- und Abschalten der Fill Area unter der Kurve an.

fontSize => $n

Fontgröße der Achsenbeschriftungen. Aus dieser Größe wird die Größe der sonstigen Fonts (Titel, Y-Titel) abgeleitet.

height => $n (Default: 300)

Höhe eines Diagramms in Pixeln.

name => $name (Default: 'dgr')

Name der Diagramm-Gruppe. Der Name wird als CSS-Id für den äußeren div-Container der Diagramm-Gruppe und als Namespace für die Funktionen genutzt.

scaleY => $bool (Default: 1)

Biete einen Button zur Y-Skalierung der Kurvendaten an.

shape => $shape (Default: scatter: 'Spline', scattergl: 'Linear')

Anfangsauswahl des Shape-Menüs auf allen Diagrammen. Der Default hängt von Attribut type ab. Mögliche Werte: 'Spline', 'Linear', 'Marker'.

strict => $bool (Default: 1)

Melde Fehler mittels alert(), nicht nur via console.log().

type => 'scatter'|'scattergl' (Default: 'scatter')

Art des Diagramms. Bei 'scattergl' ist der Umgang mit größeren Datenmengen performanter, insbesondere bei der Anzeige von Markert. Allerdings wird die Kurvenform 'spline' nicht unterstützt und im Rangeslider wird keine verkleinerte Form des Graphs angezeigt.

xAxisType => 'date'|'linear' (Default: 'date')

Art der X-Achse: date=Zeit, linear=numerisch

xTitle => $str

Text unterhalb der X-Achse.

Returns

Objekt

Description

Instantiiere ein Objekt der Klasse und liefere eine Referenz auf dieses Objekt zurück.

Objektmethoden

html() - Generiere HTML

Synopsis

  $html = $dgr->html($h);

Returns

HTML-Code (String)

Description

Liefere den HTML-Code der Diagramm-Gruppe.

Leere Diagrammgruppe

Wenn die Liste der Parameter leer ist, liefert die Methode html() einen Leerstring.

Leeres Diagramm

Besitzt ein Parameter keine Daten (die Arrays x und y sind leer), wird der Plot-Bereich des betreffenden Diagramms leer dargestellt. Die Achsen werden gemäß xMin, xMax, yMin, yMax skaliert. Fehlen auch diese Angaben, nimmt Plotly.js eine Default-Achsen-Skalierung vor (Zeitbereich: 2000-01-01 00:00:00 bis 2001-01-01 00:00:00, Y-Wertebereich: -1 bis 4).

Private Methoden

htmlDiagram() - Generiere HTML für ein Diagramm

Synopsis

  $html = $dgr->htmlDiagram($h,$i,$par,$paperBackground,$debug);

Arguments

$h

Generator für HTML-Code.

$i

Nummer des Diagramms.

Returns

HTML-Code (String)

Description

Genererie den HTML-Code für ein Diagramm und liefere diesen zurück.

jsDiagram() - Generiere JavaScript für ein Diagramm

Synopsis

  $js = $dgr->jsDiagram($j,$i,$par);

Arguments

$j

JSON-Generator

$i

Nummer des Diagramms.

$par

Zeitreihen-Objekt.

Returns

JavaScript-Code (String)

Description

Genererie den JavaScript-Code für ein Diagramm und liefere diesen zurück.

VERSION

1.204

AUTHOR

Frank Seitz, http://fseitz.de/

COPYRIGHT

Copyright (C) 2022 Frank Seitz

LICENSE

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